Skip to content

Resolver: Record what failed resolutions observed, on UnableToResolveError - #2137

Draft
robhogan wants to merge 1 commit into
robhogan/plugin-change-summariesfrom
robhogan/observe-failed-resolutions
Draft

robhogan wants to merge 1 commit into
robhogan/plugin-change-summariesfrom
robhogan/observe-failed-resolutions

Conversation

@robhogan

Copy link
Copy Markdown
Collaborator

#1949 records what a successful resolution observes of the file system, but a resolution that fails throws and its record is discarded. A failed import depends on the file system just as much - creating the missing file, or a package.json that redirects to it, can make it resolve - so anything that wants to know when to retry needs the same record.

This attaches it to UnableToResolveError as unstable_observations. With unstable_incrementalResolution on, it's the record from the failed attempt. With it off, Metro replays the failure once with a fresh record. That's sound because resolution is synchronous and observes the file system only through the capabilities bound to the record, so the replay sees the same state and fails the same way. It costs one extra resolution per failure, and only for failures that break the build.

Optional dependencies aren't replayed, since their failures are expected and they re-resolve on every traversal. If a replay succeeds, a custom resolver is reading something outside its resolution context. Metro warns about that and throws the original error, without observations.

Within Metro, a hard failure already retries on the next change because DeltaCalculator keeps the module pending, so nothing here reads the record yet. It's a draft to settle the shape of the API.

Changelog: Internal

Test plan:
New unit tests.

…Error

#1949 records what a successful resolution observes of the file system, but a resolution that fails throws and its record is discarded. A failed import depends on the file system just as much - creating the missing file, or a `package.json` that redirects to it, can make it resolve - so anything that wants to know when to retry needs the same record.

This attaches it to `UnableToResolveError` as `unstable_observations`. With `unstable_incrementalResolution` on, it's the record from the failed attempt. With it off, Metro replays the failure once with a fresh record. That's sound because resolution is synchronous and observes the file system only through the capabilities bound to the record, so the replay sees the same state and fails the same way. It costs one extra resolution per failure, and only for failures that break the build.

Optional dependencies aren't replayed, since their failures are expected and they re-resolve on every traversal. If a replay succeeds, a custom resolver is reading something outside its resolution context. Metro warns about that and throws the original error, without observations.

Within Metro, a hard failure already retries on the next change because `DeltaCalculator` keeps the module pending, so nothing here reads the record yet. It's a draft to settle the shape of the API.

Changelog: Internal

Test plan:
New unit tests.
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 30, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant