Skip to content

v2 backwards compat: SdkError status code#2049

Open
KKonstantinov wants to merge 4 commits into
mainfrom
feature/v2-compat-fix-sdk-error-data
Open

v2 backwards compat: SdkError status code#2049
KKonstantinov wants to merge 4 commits into
mainfrom
feature/v2-compat-fix-sdk-error-data

Conversation

@KKonstantinov
Copy link
Copy Markdown
Contributor

Add SdkHttpError subclass for typed HTTP transport error handling

Motivation and Context

SdkError carries HTTP failure details (status code, status text) in its data?: unknown field. Consumers who need to inspect the HTTP status — for example, to handle 401 or 403 responses — must resort to unsafe casting:

if (error instanceof SdkError && (error.data as any)?.status === 401) { ... }

This also affects v1 migration: the old StreamableHTTPError had a typed code: number for HTTP status, but the v2 replacement SdkError uses code: SdkErrorCode (an enum, not an HTTP status). There is no typed way to access the HTTP status in v2.

How Has This Been Tested?

  • pnpm build:all — all packages build successfully
  • pnpm typecheck:all — no type errors
  • pnpm lint:all — no lint or formatting issues
  • pnpm test:all — all existing tests pass (core: 552, client: 364)
  • Updated test assertions in streamableHttp.test.ts, tokenProvider.test.ts, and sse.test.ts to verify instanceof SdkHttpError and the .status accessor

Breaking Changes

None. SdkHttpError extends SdkError, so existing catch clauses and instanceof SdkError checks continue to work. This is a purely additive change — consumers can opt in to more precise error handling via instanceof SdkHttpError without changing existing code.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Alternatives Considered

A. Generic SdkError<C> with data type map — A SdkErrorDataMap mapping each SdkErrorCode to its data shape, with SdkError<C>.data conditionally typed. Rejected because TypeScript doesn't narrow class generics via property checks — consumers can't write if (error.code === SdkErrorCode.X) and get narrowed data. Requires a helper function, which is non-standard for error handling.

B. Broaden SdkError.data to { status?: number; statusText?: string; ... } — Rejected because it's misleading: suggests every SdkError might have HTTP status fields, even NotConnected or RequestTimeout which have no HTTP context.

C. Add httpStatus accessor on SdkError base classget httpStatus(): number | undefined that extracts from data. Rejected because the base class shouldn't know about HTTP semantics, and consumers can't distinguish HTTP errors structurally at the type level.

D. HTTP error subclass (chosen)SdkHttpError extends SdkError with typed data. Standard instanceof pattern, backward compatible, follows established SDK patterns (AWS SDK v3 ServiceException, Stripe StripeAPIError, gRPC ServiceError). One new class, no generics, no type maps.

Additional context

Files changed:

  • packages/core/src/errors/sdkErrors.ts — Added SdkHttpErrorData interface and SdkHttpError class with status/statusText getters
  • packages/core/src/exports/public/index.ts — Exported SdkHttpError and SdkHttpErrorData
  • packages/client/src/client/streamableHttp.ts — Changed 5 throw sites from SdkError to SdkHttpError for HTTP failures
  • packages/client/src/client/sse.ts — Changed 1 throw site (401 after retry) from SdkError to SdkHttpError
  • packages/client/test/client/streamableHttp.test.ts — Updated assertions to use SdkHttpError
  • packages/client/test/client/tokenProvider.test.ts — Updated assertions to use SdkHttpError
  • packages/client/test/client/sse.test.ts — Updated assertions to use SdkHttpError

Design decision: The ClientHttpUnexpectedContent error in streamableHttp.ts was intentionally left as SdkError — it fires on a 200 OK response with an unexpected content type, so it doesn't carry an HTTP error status and doesn't fit the SdkHttpErrorData shape.

Consumer usage after this change:

import { SdkHttpError } from '@modelcontextprotocol/client';

try {
    await client.callTool({ name: 'foo' });
} catch (error) {
    if (error instanceof SdkHttpError) {
        console.log(error.status);      // number — no cast needed
        console.log(error.statusText);  // string | undefined
        console.log(error.code);        // SdkErrorCode (inherited)
    }
}

@KKonstantinov KKonstantinov requested a review from a team as a code owner May 11, 2026 15:44
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 11, 2026

🦋 Changeset detected

Latest commit: 4932aae

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@modelcontextprotocol/core Minor
@modelcontextprotocol/client Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 11, 2026

Open in StackBlitz

@modelcontextprotocol/client

npm i https://pkg.pr.new/@modelcontextprotocol/client@2049

@modelcontextprotocol/server

npm i https://pkg.pr.new/@modelcontextprotocol/server@2049

@modelcontextprotocol/express

npm i https://pkg.pr.new/@modelcontextprotocol/express@2049

@modelcontextprotocol/fastify

npm i https://pkg.pr.new/@modelcontextprotocol/fastify@2049

@modelcontextprotocol/hono

npm i https://pkg.pr.new/@modelcontextprotocol/hono@2049

@modelcontextprotocol/node

npm i https://pkg.pr.new/@modelcontextprotocol/node@2049

commit: 4932aae

Comment thread packages/core/src/errors/sdkErrors.ts
Comment thread packages/client/test/client/streamableHttp.test.ts Outdated
Comment thread packages/core/src/exports/public/index.ts
Comment thread packages/core/src/errors/sdkErrors.ts
Comment thread .changeset/add-sdk-http-error.md Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant