From 326ee89bd3929096b18d3a252dcaa1a420c79d89 Mon Sep 17 00:00:00 2001 From: Felix Weinberger <3823880+felixweinberger@users.noreply.github.com> Date: Mon, 29 Jun 2026 15:39:32 +0100 Subject: [PATCH] docs(migration): dual-role instanceof caveat in the Errors section (#2385) --- docs/migration/upgrade-to-v2.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/migration/upgrade-to-v2.md b/docs/migration/upgrade-to-v2.md index 4455aaa6..84b7787e 100644 --- a/docs/migration/upgrade-to-v2.md +++ b/docs/migration/upgrade-to-v2.md @@ -560,6 +560,17 @@ Replace the literal with the named code. Loud (`TS2367`) when the compared value typed `SdkErrorCode`; silent when the left side is `unknown` or a cast — grep for `=== -32000` / `=== -32001`. +**Dual-role processes: `instanceof` does not cross the packages.** +`@modelcontextprotocol/client` and `@modelcontextprotocol/server` each bundle their own +copy of these error classes, so in a process that uses both — a gateway, a host, an +in-process test — an error constructed by one package fails `instanceof` against the +class imported from the other, silently. When an error may originate from the other +package, match on stable fields instead of class identity: `error.code` values +(`SdkErrorCode` strings for SDK errors, numeric JSON-RPC codes for protocol errors, +`OAuthErrorCode` strings for OAuth errors) plus presence checks like `'status' in e`, +or reconstruct typed protocol errors with `ProtocolError.fromError(code, message, data)` +— it exists precisely because `instanceof` does not survive bundle boundaries. + **Constructing the error (test stubs, custom transports).** v1 `new StreamableHTTPError(code, message)` becomes `new SdkHttpError(code, message, data)`: the first argument is now a `SdkErrorCode`