Skip to content

Bug: SDK HttpClient throws raw SyntaxError instead of Context7Error on non-JSON error responses #1964

@marlonbarreto-git

Description

@marlonbarreto-git

Bug Description

The SDK's HttpClient.request() method calls res.json() without a try/catch in the error-response path. When the server returns a non-JSON error body (HTML 502 gateway page, plain-text 429, Cloudflare challenge page, etc.), res.json() throws a native SyntaxError that bypasses the Context7Error type system.

Affected Code

File: packages/sdk/src/http/index.ts, lines ~171-173

if (!res.ok) {
  const errorBody = (await res.json()) as { error?: string; message?: string };
  throw new Context7Error(errorBody.error || errorBody.message || res.statusText);
}

res.json() is called bare — no try/catch, no Content-Type guard.

Impact

  • Any caller using catch (error) { if (error instanceof Context7Error) ... } will miss the error entirely
  • Infrastructure errors (Cloudflare 502, AWS ALB 503, rate limiting 429 with HTML body) surface as confusing SyntaxError: Unexpected token '<' at position 0 instead of a typed error with the HTTP status
  • This affects all SDK consumers: the CLI, the MCP server, and any third-party integration using the SDK

Steps to Reproduce

  1. Configure Context7 SDK to point to a server that returns a non-JSON error
  2. (Or simulate: proxy returning HTML 502 on the API endpoint)
  3. Call any SDK method (e.g., resolveLibraryId)
  4. Observe: SyntaxError: Unexpected token '<' instead of Context7Error

Proposed Solution

Wrap res.json() in a try/catch:

if (!res.ok) {
  const errorBody = await res.json().catch(() => ({})) as { error?: string; message?: string };
  throw new Context7Error(errorBody.error || errorBody.message || res.statusText);
}

This is a one-line change (adding .catch(() => ({}))) that ensures non-JSON error bodies gracefully fall through to the res.statusText fallback message, and the error is always a typed Context7Error.

Happy to submit a PR for this fix.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions