Skip to content

Commit 7eb29bc

Browse files
docs(core): qualify ResourceNotFoundError fromError reconstruction; fix cross-bundle example
- JSDoc / changeset / migration.md now state that ProtocolError.fromError reconstructs ResourceNotFoundError for either code only when error.data carries `uri`; a bare -32002 without data.uri stays a generic ProtocolError. - migration.md example: drop the outer `instanceof ProtocolError` gate (it defeats the cross-bundle case the prose describes); the example now feeds code+data straight into fromError and tests the locally-created result.
1 parent 14131b7 commit 7eb29bc

3 files changed

Lines changed: 18 additions & 12 deletions

File tree

.changeset/resource-not-found-32602.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ identically without changes.
1717
`ProtocolErrorCode.ResourceNotFound` (`-32002`) remains importable as receive-tolerated
1818
vocabulary; clients should accept both `-32602` and `-32002` from peers (the
1919
specification's backwards-compatibility clause). The new typed `ResourceNotFoundError`
20-
class carries `data.uri`, and `ProtocolError.fromError` recognises both codes by the
21-
`data.uri` shape.
20+
class carries `data.uri`, and `ProtocolError.fromError` reconstructs it for either code
21+
when `error.data` carries `uri` — a bare `-32002` without `data.uri` stays a generic
22+
`ProtocolError`.

docs/migration.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1286,18 +1286,21 @@ with the `allowInputRequired: true` request option plus the `withInputRequired()
12861286
revisions, so v1.x peers see no change. An interim `-32002` emission that shipped in earlier v2 alphas is reverted: the era encode seam maps any handler-thrown `-32002` to `-32602` on the wire, so a handler written against the older alpha behaves identically without changes.
12871287

12881288
`ProtocolErrorCode.ResourceNotFound` (`-32002`) **remains importable** as receive-tolerated vocabulary: clients should accept both `-32602` and `-32002` from peers (the specification's backwards-compatibility clause). The new typed `ResourceNotFoundError` class carries the URI on
1289-
`.uri`, and `ProtocolError.fromError` recognizes both codes by the `data.uri` shape — recognize peers' errors by their code and `error.data`, not by `instanceof`, which does not survive bundling. Servers must not return an empty `contents` array for a non-existent resource (an
1290-
empty array is ambiguous between "exists but empty" and "does not exist").
1289+
`.uri`, and `ProtocolError.fromError` reconstructs it for either code when `error.data` carries `uri` (a bare `-32002` without `data.uri` stays a generic `ProtocolError`) — recognize peers' errors by their code and `error.data`, not by `instanceof`, which does not survive
1290+
bundling. Servers must not return an empty `contents` array for a non-existent resource (an empty array is ambiguous between "exists but empty" and "does not exist").
12911291

12921292
```typescript
12931293
import { ProtocolError, ResourceNotFoundError } from '@modelcontextprotocol/client';
12941294

12951295
try {
12961296
await client.readResource({ uri: 'file:///nope' });
12971297
} catch (error) {
1298-
const typed = error instanceof ProtocolError ? ProtocolError.fromError(error.code, error.message, error.data) : undefined;
1299-
if (typed instanceof ResourceNotFoundError) {
1300-
console.log('not found:', typed.uri);
1298+
// fromError reconstructs the typed class from code + data alone, so this
1299+
// works even when `error` crossed a bundle boundary and `instanceof` on
1300+
// the thrown object would not match.
1301+
const e = error as ProtocolError;
1302+
if (ProtocolError.fromError(e.code, e.message, e.data) instanceof ResourceNotFoundError) {
1303+
console.log('not found:', (e.data as { uri: string }).uri);
13011304
}
13021305
}
13031306
```

packages/core/src/types/errors.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,14 @@ export class ProtocolError extends Error {
8080
* SDK has always emitted on earlier revisions. The error data echoes the
8181
* requested URI.
8282
*
83-
* Recognise this error by checking `error.data.uri` is a string (a
84-
* `-32602` with `data.uri` is resource-not-found; any other `-32602` is an
85-
* ordinary Invalid Params). For backwards compatibility, clients should also
83+
* Recognise this error by checking `error.data` is exactly `{ uri: string }`
84+
* (a `-32602` whose data carries `uri` and nothing else is resource-not-found;
85+
* any other `-32602` is an ordinary Invalid Params). For backwards compatibility, clients should also
8686
* accept `-32002` as resource not found — earlier SDK builds emitted that
87-
* code, and {@linkcode ProtocolError.fromError} recognises both. Do not rely
88-
* on `instanceof` — it does not work across separately bundled copies of the
87+
* code, and {@linkcode ProtocolError.fromError} reconstructs this class for
88+
* either code **when `error.data` carries `uri`** (a bare `-32002` without
89+
* `data.uri` stays a generic {@linkcode ProtocolError}). Do not rely on
90+
* `instanceof` — it does not work across separately bundled copies of the
8991
* SDK.
9092
*/
9193
export class ResourceNotFoundError extends ProtocolError {

0 commit comments

Comments
 (0)