Errors
The ErrorInfo type that every AI Transport failure path surfaces, the numeric codes you match against, and the patterns for handling errors on the client and the agent.
Every failure surfaces as an ErrorInfo object. The same type covers AI Transport-specific failures, Ably platform errors (auth, channel attach, rate limits), and underlying network errors. Match against a specific code with the errorInfoIs utility.
ErrorInfo
The ErrorInfo type is exported from ably. AI Transport surfaces it as the rejection reason on every promise that can fail, and as the argument to every on('error') listener.
Properties
codeNumbererrorInfoIs to identify a specific failure.messageStringstatusCodeNumbercauseErrorInfo or UndefineddetailRecord<string, string> or UndefinedAI Transport error codes
General errors
| Code | Name | HTTP status | Description | Recovery |
|---|---|---|---|---|
| 40000 | BadRequest | 400 | The request was malformed or missing required fields. | Check the request payload and ensure all required fields are present. |
| 40003 | InvalidArgument | 400 | An argument passed to a session or run method was invalid. | Verify the arguments match the expected types and constraints. |
| 40160 | InsufficientCapability | 401 | The Ably channel rejected a publish for a capability reason. The token does not permit the operation. | Add the missing capability to the token. See authentication. |
Session and run errors
| Code | Name | HTTP status | Description | Recovery |
|---|---|---|---|---|
| 104000 | EncoderRecoveryFailed | 500 | The encoder failed to recover after a publish error. One or more updateMessage calls could not recover a failed append pipeline. | End the Run with reason 'error' and start a new one. The client sees the partial response up to the failure point. |
| 104001 | SessionSubscriptionError | 500 | A session-level channel subscription callback threw unexpectedly. | Check the subscription callback for unhandled exceptions. Inspect the underlying error for details. |
| 104002 | CancelListenerError | 500 | The cancel listener or onCancel hook threw while processing a cancel message. | Check the onCancel hook for unhandled exceptions. The Run may not respond to subsequent cancels. |
| 104003 | RunLifecycleError | 500 | A publish within a Run failed (lifecycle event, message, or codec event). | Check channel permissions and connection state. Surface the error to the calling HTTP handler so the client's pending send fails. |
| 104004 | SessionClosed | 400 | An operation was attempted on a session that has already been closed. | Create a new session. Do not reuse a closed session. |
| 104005 | SessionSendFailed | 500 | A send failed: either the core's channel publish failed, or the Vercel chat transport's agent-invocation POST failed (network error or non-2xx response). | Check the API endpoint URL, network connectivity, and authentication. Inspect the underlying error for details. |
| 104006 | ChannelContinuityLost | 500 | The Ably channel lost message continuity. The channel entered FAILED, SUSPENDED, or DETACHED, or re-attached with resumed: false. Active streams can no longer be guaranteed to receive all events. | Surfaced via the session's on('error') and the agent session's onError option. End active Runs; subsequent operations can resume once the channel reattaches. |
| 104007 | ChannelNotReady | 400 | An operation was attempted but the channel is not in a usable state (not ATTACHED or ATTACHING). | Wait for the channel to attach before retrying, or inspect channel state and connection state for the underlying cause. |
| 104008 | StreamError | 500 | An error occurred while piping a response stream to the channel. Either the source event stream threw (LLM provider rate limit, model error, network failure) or an underlying publish failed mid-stream. | Inspect cause for the provider error. End the Run with reason 'error'. The error is also returned on StreamResult.error from Run.pipe. |
| 104010 | InputEventNotFound | 504 | The agent attached to the channel and waited for the input events the invocation points at (rewind + live wait) but inputEventLookupTimeoutMs lapsed without seeing them. | Surface the rejection from Run.start() as a non-2xx response so the client's pending send fails. The client retries with a fresh send. |
Auth and channel errors
Auth and channel errors come from the Ably platform, not AI Transport. The most common codes you encounter:
| Code | Description | Recovery |
|---|---|---|
| 40142 | Token expired. | Refresh the token (handled automatically with authUrl/authCallback). |
| 40300 | Forbidden. | The token is valid but not authorised for this resource. |
| 80000 | Channel attach failed. | Check the channel name and capability. |
| 90000 | Internal channel error. | Retry the operation. If the error persists, contact support. |
The full Ably error code list lives at Ably error codes.
Match an ErrorInfo against a code
errorInfoIs(errorInfo: Ably.ErrorInfo, error: ErrorCode): booleanerrorInfoIs returns true if the ErrorInfo's code matches the supplied ErrorCode. Use it in error handlers to branch on specific failures without writing string comparisons against the message.
1
2
3
4
5
6
7
import { errorInfoIs, ErrorCode } from '@ably/ai-transport';
session.on('error', (error) => {
if (errorInfoIs(error, ErrorCode.SessionClosed)) {
reconnect();
}
});Example
Handle session-level and run-level errors separately. The client subscribes to session errors. The agent uses the onError option on AgentSessionOptions for session-wide events and the run runtime's onError for per-Run failures.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import { errorInfoIs, ErrorCode } from '@ably/ai-transport';
// Client side: subscribe to session-level errors.
session.on('error', (error) => {
console.error(`Error ${error.code}: ${error.message}`);
if (errorInfoIs(error, ErrorCode.ChannelContinuityLost)) {
showReconnectBanner();
}
});
// Agent side: handle session and run-level errors separately.
const agentSession = createAgentSession({
client: ably,
channelName,
codec,
onError(error) {
console.error('Session error:', error);
},
});
await agentSession.connect();
const run = agentSession.createRun(invocation, {
signal: req.signal,
onError(error) {
console.error('Run error:', error);
},
});
// End a Run with reason 'error' when piping fails.
try {
const result = await run.pipe(llmStream);
await run.end(result.reason);
} catch (error) {
await run.end('error');
}