From 64041e3072e968002e2085445217ccde1f36e5d7 Mon Sep 17 00:00:00 2001 From: Aaditya Date: Wed, 14 Oct 2026 00:35:57 +0530 Subject: [PATCH] fix(session): reject an unknown configured provider before unbound routing (#2976) When every registered deep provider rejected a target, select() returned an intentionally unbound success for any concrete environment selector, including one that names no registered provider. A misconfigured REA_ANALYSIS_PROVIDER therefore opened the target unbound, and the later deep-operation diagnostic blamed target support instead of the unknown configuration. The same identifier requested explicitly already failed with unknown_provider. Take the unbound shortcut only for a registered environment preference. An unknown configured identifier now reaches concrete selection and fails with unknown_provider, matching the explicit request. Registered preferences and auto still leave artifact-only targets unbound. Fixes #2592 --- .../binary/AnalysisProviderRegistry.test.ts | 22 +++++++++++++++++++ .../binary/AnalysisProviderRegistry.ts | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/application/binary/AnalysisProviderRegistry.test.ts b/src/application/binary/AnalysisProviderRegistry.test.ts index 8eae6c9c9..fde2f6718 100644 --- a/src/application/binary/AnalysisProviderRegistry.test.ts +++ b/src/application/binary/AnalysisProviderRegistry.test.ts @@ -186,6 +186,28 @@ describe("analysis provider registry: binding failures and cancellation", () => expect(explicit.error.reason).toBe("target_unsupported"); }); + it("rejects an unknown environment preference even when every candidate rejects the target", async () => { + const alpha = candidate("alpha"); + const misconfigured = new AnalysisProviderRegistry( + [alpha.provider], + "missing", + ); + + for (const selected of [ + await misconfigured.select(ARTIFACT_TARGET), + await misconfigured.select(ARTIFACT_TARGET, "missing"), + ]) { + if (selected.ok) throw new Error("expected unknown provider rejection"); + expect(projectAnalysisError(selected.error)).toMatchObject({ + details: { + selection_reason: "unknown_provider", + requested_provider_id: "missing", + candidate_ids: ["alpha"], + }, + }); + } + }); + it("does not bind a profile with unresolved version or adapter failure", async () => { const unresolved = candidate("unresolved", { profile: "missing" }); const failed = candidate("failed", { profile: "error" }); diff --git a/src/application/binary/AnalysisProviderRegistry.ts b/src/application/binary/AnalysisProviderRegistry.ts index 5b7e78813..033677881 100644 --- a/src/application/binary/AnalysisProviderRegistry.ts +++ b/src/application/binary/AnalysisProviderRegistry.ts @@ -176,7 +176,7 @@ export class AnalysisProviderRegistry { return err(new AnalysisCancelledError("open_binary")); if ( request === undefined && - selector !== "auto" && + this.#byId.has(selector) && baseline.length > 0 && baseline.every( ({ targetSupport }) => targetSupport.status === "unsupported",