> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.meshapi.ai/llms.txt.
> For full documentation content, see https://developers.meshapi.ai/llms-full.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.meshapi.ai/_mcp/server.

# Error Handling

> Handle errors and streaming failures in the Node.js SDK.

# Error Handling

All API errors throw `MeshAPIApiError`, a subclass of `Error` with structured fields:

```ts
import { MeshAPI, MeshAPIApiError } from "meshapi-node-sdk";

try {
  const response = await client.chat.completions.create({
    model: "openai/gpt-4o-mini",
    messages: [{ role: "user", content: "Hello" }],
  });
  console.log(response.choices[0]?.message.content);

} catch (err) {
  if (err instanceof MeshAPIApiError) {
    console.error(`[${err.status}] ${err.errorCode}: ${err.message}`);
    console.error("Request ID:", err.requestId);

    switch (err.errorCode) {
      case "rate_limit_exceeded":
        console.log(`Retry after ${err.retryAfterSeconds}s`);
        break;

      case "spend_limit_exceeded":
        console.log("Spend cap reached — add credits.");
        break;

      case "unauthorized":
        console.log("Invalid or missing API key.");
        break;

      case "model_not_found":
        console.log("Model not supported by the gateway.");
        break;

      case "upstream_error":
        console.log("Upstream provider error:", err.providerError);
        break;

      case "validation_error":
        console.log("Validation details:", err.details);
        break;
    }
  } else {
    // Network error, AbortError, etc.
    throw err;
  }
}
```

## Error codes reference

| Code                   | HTTP | Description                                   |
| ---------------------- | ---- | --------------------------------------------- |
| `unauthorized`         | 401  | Invalid or missing API key                    |
| `forbidden`            | 403  | Key suspended or access denied                |
| `not_found`            | 404  | Resource not found                            |
| `model_not_found`      | 404  | Model not supported                           |
| `validation_error`     | 422  | Request body failed validation                |
| `unprocessable_entity` | 422  | Request cannot be processed                   |
| `rate_limit_exceeded`  | 429  | RPM or RPD limit hit                          |
| `spend_limit_exceeded` | 402  | Per-key spend cap reached                     |
| `upstream_error`       | 500  | Upstream provider error                       |
| `gateway_timeout`      | 500  | Upstream provider timed out                   |
| `internal_error`       | 500  | Server error                                  |
| `parse_error`          | —    | Response body could not be parsed (SDK-level) |

## Streaming errors

Mid-stream errors (sent as SSE frames before `[DONE]`) are automatically detected and thrown as `MeshAPIApiError` within the `for await` loop:

```ts
try {
  for await (const chunk of stream) {
    process.stdout.write(chunk.choices[0]?.delta.content ?? "");
  }
} catch (err) {
  if (err instanceof MeshAPIApiError) {
    // e.g. errorCode: "upstream_error", status: 0 (headers already sent)
    console.error("Stream error:", err.errorCode, err.message);
  }
}
```