Skip to content

fix(mcp): don't mask a resolver failure with an un-wired instance#156

Merged
suleimansh merged 1 commit into
mainfrom
fix/mcp-resolver-no-swallow
Jul 2, 2026
Merged

fix(mcp): don't mask a resolver failure with an un-wired instance#156
suleimansh merged 1 commit into
mainfrom
fix/mcp-resolver-no-swallow

Conversation

@suleimansh

Copy link
Copy Markdown
Member

Closes #149.

resolveOrConstruct caught any resolver throw and fell back to new Ctor(). So a real DI misconfiguration — a token the container does own, whose construction throws because a constructor dependency is missing — was silently replaced by a fresh, un-wired instance, masking the bug. This contradicts the loud-resolver philosophy resolveHandleDeps/createResolver enforce elsewhere.

The interface has no way to tell "no binding" from "threw", so I added an optional McpResolver.has?(token) hook:

  • Resolvers that implement it (the built-in createResolver now does) get a precise path: only owned tokens go through resolve(), and a genuine construction failure propagates loudly.
  • Resolvers without it keep the legacy fallback (a resolve miss falls back to a plain constructor), so this is backward compatible.

Tests: new runtime/handle-deps.test.ts — propagation on an owned-but-failing token, skip-resolve for un-owned tokens, and the two legacy fallback paths. pnpm typecheck + pnpm test green (111, +6). Minor changeset (additive has? + createResolver().has).

resolveOrConstruct caught any resolver throw and fell back to new Ctor(), so a
real DI misconfiguration (a registered token whose construction fails) was
silently replaced by a fresh un-wired instance, contradicting the package's
loud-resolver philosophy.

Add an optional McpResolver.has(token) hook. When present (createResolver now
implements it), only owned tokens go through resolve() and a genuine
construction failure propagates. Resolvers without has() keep the legacy
fallback, so the change is backward compatible.

Closes #149
@suleimansh suleimansh added bug Something isn't working priority: medium Worth doing, not urgent labels Jul 2, 2026
@suleimansh suleimansh self-assigned this Jul 2, 2026
@suleimansh suleimansh merged commit 964e3d8 into main Jul 2, 2026
2 checks passed
@suleimansh suleimansh deleted the fix/mcp-resolver-no-swallow branch July 2, 2026 22:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working priority: medium Worth doing, not urgent

Projects

None yet

Development

Successfully merging this pull request may close these issues.

mcp: resolveOrConstruct swallows resolver errors and builds an unwired instance

1 participant