Skip to content

fix(core): retry failed location initialization - #46957

Open
kitlangton wants to merge 2 commits into
v2from
retry-location-boot
Open

fix(core): retry failed location initialization#46957
kitlangton wants to merge 2 commits into
v2from
retry-location-boot

Conversation

@kitlangton

@kitlangton kitlangton commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Why

A Location can fail to boot because its config references a missing file, or on Unix because its directory is a regular file or is unreadable. Repairing the filesystem still leaves subsequent loads failing: the cache gives any existing path an infinite idle lifetime, including failed builds. Explicit invalidation recovers the same repaired directory.

What Changes

Cache retention now follows the graph's build result instead of local path existence.

Case Result
Missing {file:username.txt} config reference created Next acquisition boots successfully without manual invalidation
File replaced with a directory (Unix) Next acquisition boots successfully without manual invalidation
Directory permissions restored from 000 to 755 (non-root Unix) Next acquisition boots successfully without manual invalidation
Missing directory created Still retries successfully
Healthy graph, including a workspace-only directory Still retained and reused after borrowers release
Concurrent acquisitions during a failing boot Share that build's failure; later acquisitions can retry

Failed build ownership

Eviction runs once at the shared LayerMap build boundary, not once per failed caller. A short-lived build identity prevents an old, explicitly invalidated boot from evicting its replacement. Successful builds retain infinite idle TTL; workspace liveness never consults the host filesystem.

Failure eviction starts immediately in the map owner's scope. Removing the cache entry permits retry, while owner-scoped cleanup can wait for the failed lookup to finish. This avoids a self-join when all acquisition scopes close before the boot fails.

Scope

Only Location boot-failure retention and its regression tests. This is complementary to #46074, which fixes cleanup of invalidated borrowed entries in Effect; it neither duplicates that dependency patch nor changes the public API.

Verification

# Repository root
bun install --frozen-lockfile
bunx prettier --check packages/core/src/location-services.ts packages/core/test/location-layer.test.ts
bunx oxlint packages/core/src/location-services.ts packages/core/test/location-layer.test.ts
git diff --check

# packages/core
bun run test test/location-layer.test.ts
bun run test test/location-layer.test.ts --test-name-pattern 'config reference'
bun run test test/location-layer.test.ts test/location.test.ts test/location-filesystem.test.ts test/location-mutation.test.ts test/session-move.test.ts test/session-remove.test.ts
for iteration in 1 2 3 4 5; do bun run test test/location-layer.test.ts; done
bun typecheck
bun run test
  • Baseline red: on unchanged d9c85d8d95, both repaired-path cases failed; explicit-invalidation controls and the existing Location tests passed (14 pass, 2 fail).
  • Portable fixture baseline: temporarily restored the byte-for-byte d9c85d8d95 cache implementation, verified with git diff --exit-code. The missing config-reference fixture produced two failed retry cases and one passing explicit-invalidation control. Restored the production implementation unchanged afterward.
  • Focused green: 24 Location-layer tests, including five repeated runs; 57 tests across the six Location/move/remove files passed.
  • Concurrency: real cache and production graph, with a gated decoration of LocationWatcher for deterministic ordering. Covers shared failure through get, contextEffect, and contextEffectOption; eight failed borrowers released after repair; late failure after replacement; failed-build finalization; and acquisition scopes closing before failure. The late-failure test rejected naive eviction, and the closed-scope test rejected synchronous self-joining cleanup.
  • Full core suite: 4,030 pass, 39 skip, 0 fail across 227 files.
  • Core typecheck, formatting, and lint passed. The normal pre-push workspace typecheck passed all 33 tasks; no hooks bypassed.
  • Verified locally on non-root macOS with Bun 1.4.0. No live server restart or user-session mutation was used.

Platform coverage

The initial Windows run failed three new tests at their first-load assertion: the file-path fixture boots there instead of failing. On the unchanged base, macOS fails in Config.discover when accessing <file>/.opencode (ENOTDIR / BadResource); the Instance, Config, and FSUtil implementations are unchanged by this PR. This was a nonportable failure fixture, not a failed repair or retry.

The fixture-only correction retains the file-path regressions on Unix and skips permission cases on Windows/root. It adds a real missing-config-reference failure and repair on every platform, including concurrent failed borrowers. The shared-build, cancellation, replacement-identity, and finalization tests still run on every platform. Production code is unchanged by the correction.

CI green on 8301288a4c: Windows unit tests, Linux unit tests, and typecheck all passed. The remaining reported PR checks also passed.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant