Error Handling
Error handling in experimental-agent—methods throw typed errors. Error types, try/catch patterns, backend patterns, and sandbox error handling.
Methods throw typed errors. Use try/catch to handle them.
The Pattern
import { createUIMessageStreamResponse } from "ai";
try {
const stream = await session.stream();
return createUIMessageStreamResponse({ stream });
} catch (error) {
return Response.json({ error: (error as Error).message }, { status: 404 });
}Wrap calls in try/catch and check the error type for specific handling.
Error Types
experimental-agent exports these error classes:
| Error | When |
|---|---|
SessionNotFoundError | Session ID doesn't exist |
MessageNotFoundError | Message ID doesn't exist |
SandboxNotFoundError | Sandbox not found |
SandboxError | Sandbox operation failed (exec, readFile, etc.) |
StorageError | Storage operation failed |
StorageConflictError | Optimistic locking conflict (e.g. runId mismatch) |
Checking Errors
Import error classes and use instanceof in catch blocks:
import {
SessionNotFoundError,
StorageError,
} from "experimental-agent";
try {
const result = await session.history();
return Response.json(result);
} catch (error) {
if (error instanceof SessionNotFoundError) {
return Response.json({ error: "Session not found" }, { status: 404 });
}
if (error instanceof StorageError) {
return Response.json({ error: (error as Error).message }, { status: 500 });
}
throw error;
}Error Handling in Backend Flows
Send and stream
import { createUIMessageStreamResponse } from "ai";
import { myAgent } from "@/agent";
const session = myAgent.session(chatId);
await session.send(message);
const stream = await session.stream();
return createUIMessageStreamResponse({ stream });If send or stream fails, it throws. Wrap in try/catch at the route level:
try {
const session = myAgent.session(chatId);
await session.send(message);
const stream = await session.stream();
return createUIMessageStreamResponse({ stream });
} catch (error) {
return Response.json({ error: (error as Error).message }, { status: 500 });
}Reconnect to stream
try {
const stream = await session.stream();
return createUIMessageStreamResponse({ stream });
} catch (error) {
return Response.json({ error: (error as Error).message }, { status: 404 });
}Session history (load messages)
import { SessionNotFoundError } from "experimental-agent";
try {
const result = await session.history();
return Response.json(result);
} catch (error) {
if (error instanceof SessionNotFoundError) {
return Response.json({ error: "Session not found" }, { status: 404 });
}
return Response.json({ error: (error as Error).message }, { status: 500 });
}Approval resolution
try {
await session.send({
type: "approval",
approval: { approvalId, approved, reason },
});
return Response.json({ success: true });
} catch (error) {
return Response.json({ error: (error as Error).message }, { status: 400 });
}Consistent response format
import { SessionNotFoundError } from "experimental-agent";
try {
// ... operation
} catch (error) {
const status = error instanceof SessionNotFoundError ? 404 : 500;
return Response.json(
{ error: (error as Error).message, code: (error as Error).name },
{ status }
);
}Error Handling in Tools
Tools can throw errors. Thrown errors become tool-result errors and surface as output-error in the stream:
import { tool } from "ai";
import { z } from "zod";
const ReadFile = tool({
description: "Read a file",
parameters: z.object({ path: z.string() }),
execute: async ({ path }) => {
const content = await fs.readFile(path, "utf-8");
if (!content) throw new Error("File is empty");
return content;
},
});Use try/catch in execute when you need to transform or handle errors before rethrowing:
execute: async ({ path }) => {
try {
return await fs.readFile(path, "utf-8");
} catch (e) {
throw new Error(`Failed to read ${path}: ${e instanceof Error ? e.message : String(e)}`);
}
},Storage Errors
Storage methods throw on failure.
- Not found — Return
null(e.g.session.getwhen the session doesn't exist) - Conflict — Throw
StorageConflictErrorfor optimistic locking failures - Other failures — Throw
StorageError
See Custom Storage for details.
Sandbox Errors
Sandbox methods throw SandboxError on failure:
import { SandboxError } from "experimental-agent";
try {
const result = await sandbox.exec({ command: "npm", args: ["install"] });
console.log(result.stdout, result.stderr, result.exitCode);
} catch (error) {
if (error instanceof SandboxError) {
console.error("Sandbox failed:", error.message);
return;
}
throw error;
}Next Steps
- API Routes — Full route patterns with error handling
- Custom Storage — Storage error handling
- Sandbox Setup — Sandbox API and error handling