or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

agent-connection.mdclient-connection.mderrors.mdindex.mdinterfaces.mdprotocol-types.mdstream.md
tile.json

errors.mddocs/

Error Handling

The ACP SDK uses JSON-RPC 2.0 error handling with the RequestError class. All protocol-level errors are represented using standardized error codes.

RequestError Class

JSON-RPC error class for representing errors during method execution.

class RequestError extends Error {
  constructor(code: number, message: string, data?: unknown);

  code: number;
  data?: unknown;

  // Standard error factories
  static parseError(data?: unknown, additionalMessage?: string): RequestError;
  static invalidRequest(data?: unknown, additionalMessage?: string): RequestError;
  static methodNotFound(method: string): RequestError;
  static invalidParams(data?: unknown, additionalMessage?: string): RequestError;
  static internalError(data?: unknown, additionalMessage?: string): RequestError;

  // ACP-specific errors
  static authRequired(data?: unknown, additionalMessage?: string): RequestError;
  static resourceNotFound(uri?: string): RequestError;

  // Conversion methods
  toResult<T>(): Result<T>;
  toErrorResponse(): ErrorResponse;
}

Constructor

Creates a new RequestError with a specific code, message, and optional data.

constructor(code: number, message: string, data?: unknown)

Parameters:

  • code (number): JSON-RPC error code
  • message (string): Human-readable error message
  • data (unknown, optional): Additional error data

Usage Example:

throw new RequestError(-32001, 'Custom error', { detail: 'explanation' });

Standard Error Factories

parseError

Invalid JSON was received. An error occurred while parsing the JSON text.

static parseError(data?: unknown, additionalMessage?: string): RequestError

Error Code: -32700

Usage Example:

try {
  JSON.parse(invalidJson);
} catch {
  throw RequestError.parseError({ received: invalidJson });
}

invalidRequest

The JSON sent is not a valid Request object.

static invalidRequest(data?: unknown, additionalMessage?: string): RequestError

Error Code: -32600

Usage Example:

if (!isValidRequest(message)) {
  throw RequestError.invalidRequest(message, 'Missing required field: method');
}

methodNotFound

The method does not exist or is not available.

static methodNotFound(method: string): RequestError

Error Code: -32601

Usage Example:

if (!supportedMethods.includes(method)) {
  throw RequestError.methodNotFound(method);
}

invalidParams

Invalid method parameter(s).

static invalidParams(data?: unknown, additionalMessage?: string): RequestError

Error Code: -32602

Usage Example:

if (params.sessionId == null) {
  throw RequestError.invalidParams({ missing: 'sessionId' });
}

internalError

Internal JSON-RPC error.

static internalError(data?: unknown, additionalMessage?: string): RequestError

Error Code: -32603

Usage Example:

try {
  await processRequest(params);
} catch (error) {
  throw RequestError.internalError({ originalError: error.message });
}

ACP-Specific Errors

authRequired

Authentication is required before proceeding.

static authRequired(data?: unknown, additionalMessage?: string): RequestError

Error Code: -32000

Usage Example:

if (!isAuthenticated(clientId)) {
  throw RequestError.authRequired({
    availableMethods: ['oauth', 'api_key']
  });
}

resourceNotFound

A resource (such as a file) was not found.

static resourceNotFound(uri?: string): RequestError

Error Code: -32002

Usage Example:

try {
  await fs.readFile(filePath);
} catch {
  throw RequestError.resourceNotFound('file:///path/to/file.txt');
}

Conversion Methods

toResult

Converts the error to a Result object for JSON-RPC responses.

toResult<T>(): Result<T>

Returns:

{
  error: {
    code: number;
    message: string;
    data?: unknown;
  }
}

Usage Example:

try {
  const result = await processRequest(params);
  return { result };
} catch (error) {
  if (error instanceof RequestError) {
    return error.toResult();
  }
  throw error;
}

toErrorResponse

Converts the error to an ErrorResponse object.

toErrorResponse(): ErrorResponse

Returns:

{
  code: number;
  message: string;
  data?: unknown;
}

Error Handling Patterns

In Agent Implementations

import { Agent, RequestError } from '@agentclientprotocol/sdk';

const agent: Agent = {
  async newSession(params) {
    // Check authentication
    if (!isAuthenticated()) {
      throw RequestError.authRequired({
        message: 'Please authenticate before creating a session'
      });
    }

    // Validate parameters
    if (!params.mcpServers) {
      throw RequestError.invalidParams(
        { missing: 'mcpServers' },
        'mcpServers parameter is required'
      );
    }

    try {
      const sessionId = await createSession(params);
      return {
        sessionId,
        availableModes: getAvailableModes(),
        currentMode: 'code'
      };
    } catch (error) {
      // Convert internal errors
      throw RequestError.internalError({
        detail: error.message
      });
    }
  }
};

In Client Implementations

import { Client, RequestError } from '@agentclientprotocol/sdk';

const client: Client = {
  async readTextFile(params) {
    try {
      const content = await fs.readFile(params.uri, 'utf-8');
      return { content };
    } catch (error) {
      if (error.code === 'ENOENT') {
        throw RequestError.resourceNotFound(params.uri);
      }
      throw RequestError.internalError({
        fsError: error.message
      });
    }
  },

  async createTerminal(params) {
    // Validate capability
    if (!clientCapabilities.terminal) {
      throw RequestError.methodNotFound('terminal/create');
    }

    try {
      const terminal = spawn(params.command, params.args);
      const terminalId = registerTerminal(terminal);
      return { terminalId };
    } catch (error) {
      throw RequestError.internalError({
        spawnError: error.message
      });
    }
  }
};

Catching Errors

import { ClientSideConnection, RequestError } from '@agentclientprotocol/sdk';

const connection = new ClientSideConnection((agent) => client, stream);

try {
  const session = await connection.newSession({ mcpServers: [] });
  console.log('Session created:', session.sessionId);
} catch (error) {
  if (error instanceof RequestError) {
    switch (error.code) {
      case -32000:  // authRequired
        console.error('Authentication required');
        await connection.authenticate({
          method: 'oauth',
          credentials: await getCredentials()
        });
        // Retry newSession
        break;

      case -32601:  // methodNotFound
        console.error('Agent does not support this method');
        break;

      case -32602:  // invalidParams
        console.error('Invalid parameters:', error.data);
        break;

      case -32603:  // internalError
        console.error('Agent internal error:', error.message);
        if (error.data) {
          console.error('Details:', error.data);
        }
        break;

      default:
        console.error(`Error ${error.code}: ${error.message}`);
    }
  } else {
    // Non-protocol error
    throw error;
  }
}

Zod Validation Errors

The SDK automatically converts Zod validation errors to invalidParams errors:

// In agent/client implementation
async initialize(params) {
  // SDK validates params using Zod schema
  // If validation fails, automatically throws:
  // RequestError.invalidParams(zodError.format())

  // Your code only runs with valid params
  return { ... };
}

Error Response Format

Errors are transmitted as JSON-RPC 2.0 error responses:

{
  "jsonrpc": "2.0",
  "id": 123,
  "error": {
    "code": -32002,
    "message": "Resource not found: file:///path/to/file.txt",
    "data": {
      "uri": "file:///path/to/file.txt"
    }
  }
}

Error Code Reference

CodeNameDescription
-32700Parse ErrorInvalid JSON was received
-32600Invalid RequestThe JSON is not a valid Request object
-32601Method Not FoundThe method does not exist
-32602Invalid ParamsInvalid method parameter(s)
-32603Internal ErrorInternal JSON-RPC error
-32000Auth RequiredAuthentication required (ACP-specific)
-32002Resource Not FoundResource not found (ACP-specific)

Best Practices

  1. Use Factory Methods: Always use static factory methods instead of constructing errors manually

    // Good
    throw RequestError.resourceNotFound(uri);
    
    // Avoid
    throw new RequestError(-32002, 'Resource not found');
  2. Include Useful Data: Provide additional context in the data parameter

    throw RequestError.invalidParams({
      missing: 'sessionId',
      received: params
    });
  3. Catch and Convert: Convert application errors to RequestError

    try {
      await operation();
    } catch (error) {
      throw RequestError.internalError({
        originalError: error.message
      });
    }
  4. Check Error Codes: Always check error codes when catching

    if (error instanceof RequestError && error.code === -32000) {
      // Handle auth required
    }
  5. Don't Leak Secrets: Be careful not to include sensitive data in error details

    // Bad - leaks password
    throw RequestError.authRequired({ password: params.password });
    
    // Good
    throw RequestError.authRequired({ method: params.method });

Notes

  • All errors extend the standard Error class
  • The SDK automatically handles Zod validation errors
  • Error codes follow JSON-RPC 2.0 specification
  • ACP-specific errors use codes in the -32000 to -32099 range
  • Errors are automatically serialized for JSON-RPC transmission
  • Both synchronous and asynchronous errors are handled consistently