Agent SDK · Reference

Error handling.

Run and stream errors, exponential-backoff retries, and partial results after a failure.

MatildaAgentRunError

Thrown on HTTP-level failures (non-2xx response from the server).

TypeScript
class MatildaAgentRunError extends Error {
  readonly status: number;       // HTTP status code
  readonly responseText: string; // Raw response body
}

MatildaAgentStreamError

Thrown by run() when the stream emits an error event (unless throwOnStreamError: false). Carries the full AgentRunResult with whatever was collected before the error.

TypeScript
class MatildaAgentStreamError extends Error {
  readonly code: ChatErrorCode;
  readonly errors: ReadonlyArray<{ code: ChatErrorCode; message: string }>;
  readonly result: AgentRunResult;
}
TypeScript
import { MatildaAgentStreamError, MatildaAgentRunError } from '@maincode-ai/matilda-agent-sdk';

try {
  await runner.run(agent, input);
} catch (err) {
  if (err instanceof MatildaAgentStreamError) {
    console.log('Stream error code:', err.code);
    console.log('Partial output before error:', err.result.finalOutput);
    console.log('All errors:', err.errors);
  } else if (err instanceof MatildaAgentRunError) {
    console.log('HTTP error status:', err.status);
    console.log('Response body:', err.responseText);
  } else {
    throw err;
  }
}

SafetyReplaceError

Thrown by streamText(), runText(), streamObject(), and runObject() when the server replaces the output via a safety filter. The message property contains the replacement text (or empty string), and categories lists the safety categories.

TypeScript
class SafetyReplaceError extends Error {
  readonly categories: string[];
}

MatildaObjectParseError

Thrown by streamObject() / runObject() when the response cannot be parsed as JSON or fails zod validation — e.g. a truncated stream (see Structured output). raw holds the full response text; cause is the underlying JSON.parse or zod error. Safety replacement does not surface here — it throws SafetyReplaceError first.

TypeScript
class MatildaObjectParseError extends Error {
  readonly raw: string;
  readonly cause: unknown;
}

AuthError

Thrown by auth flows. The code field is an OAuth error code. The retryable field distinguishes transient failures from permanent ones.

TypeScript
class AuthError extends Error {
  readonly code: string;
  readonly retryable: boolean;
}

Chat error codes (ChatErrorCode)

These codes are emitted via the error stream event and appear in AgentRunResult.errors:

CodeDescription
internal_errorServer-side failure.
upstream_unavailableThe AI model is not responding.
rate_limitedToo many requests.
content_blockedSafety filter blocked the content.
stream_abortedThe stream was interrupted before completion.
deadline_exceededThe response did not finish before the deadline.
context_too_largeThe conversation is too long for the model.
stalledNo SSE events for the configured stall window.
stream_expiredThe durable stream buffer expired (resume path only).
unknownUnclassified error (old server without typed codes).

Stall watchdog

The streaming parser arms an idle-event watchdog. If no SSE event arrives for stallTimeoutMs milliseconds, the stream is considered dead and aborted with a 'stalled' error.

  • Default: 45_000 ms (DEFAULT_AGENT_STALL_TIMEOUT_MS)
  • Disable: Pass stallTimeoutMs: 0 in AgentRunOptions (not recommended)

Retry behaviour

The SDK retries retryable errors within a single turn. Retries are controlled by maxRetries (default: 0 — no retries).

Retryable errors:

  • HTTP 429 (rate limited), 408 (request timeout), 5xx (server errors)
  • Network errors: UND_ERR_SOCKET, UND_ERR_FETCH_ERROR, ETIMEDOUT, ECONNRESET
  • SSE stall watchdog (stalled error code)
  • TimeoutError (but not AbortError)

Retry delay: Exponential backoff with jitter, capped at 30 seconds.

Important: Retries only happen when no text has been yielded to the consumer yet. Retrying past that point would replay text the caller already has.

When a retry occurs, a turn.retrying event is emitted:

TypeScript
for await (const event of runner.stream(agent, input, { maxRetries: 3 })) {
  if (event.type === 'turn.retrying') {
    console.log(`Retry ${event.attempt}/${event.maxRetries} in ${event.delayMs}ms: ${event.error.message}`);
  }
}

Error handling example

TypeScript
import {
  Runner,
  MatildaAgentStreamError,
  MatildaAgentRunError,
  SafetyReplaceError,
} from '@maincode-ai/matilda-agent-sdk';

const runner = new Runner();

try {
  const text = await runner.runText(agent, 'Hello!');
  console.log(text);
} catch (err) {
  if (err instanceof MatildaAgentStreamError) {
    console.error(`Stream error: ${err.code}${err.message}`);
    console.log('Partial output:', err.result.finalOutput);
  } else if (err instanceof MatildaAgentRunError) {
    if (err.status === 401) {
      console.error('Session expired — re-authenticate.');
    } else if (err.status === 429) {
      console.error('Rate limited — slow down.');
    } else {
      console.error(`API error ${err.status}: ${err.responseText}`);
    }
  } else if (err instanceof SafetyReplaceError) {
    console.error(`Safety filter: ${err.categories.join(', ')}`);
  } else {
    console.error('Unexpected error:', err);
  }
}