data (for example retryable, reason, capability); connections end with WebSocket close codes. Each SDK surfaces them as typed errors.
Generated from bma-executor-sdk 1.3.0 and its contract (
contracts/bma/executor, protocol bma.executor.v1.1). Install, credentials and quick starts are on the bma-executor-sdk overview; the protocol itself is described in Executor Protocol.RPC error
A JSON-RPC error returned by the peer, or returned by a handler to answer with a specific code and data.export class RpcError extends Error {
constructor(
static withReason(code: number, reason: string, message: string): RpcError
toJSON(): JsonRpcError
}
class RPCError(ExecutorError):
"""A JSON-RPC error. A handler that raises it keeps its code on the wire."""
def __init__(self, code: int, message: str, data: dict[str, Any] | None = None) -> None: ...
@classmethod
def with_reason(cls, code: int, reason: str, message: str) -> RPCError: ...
@property
def retryable(self) -> bool | None: ...
def to_wire(self) -> dict[str, Any]: ...
type RPCError struct {
Code int
Message string
Data *JSONRPCErrorData
}
Client errors
The executor end: not connected, stopped, replaced by another executor with the same identity (close code 4004: stop, do not reconnect), reconnects exhausted.export class NotConnectedError extends Error {
constructor(message = 'executor channel is not connected')
}
export class ClientStoppedError extends Error {
constructor()
}
export class RequestTimeoutError extends Error {
constructor(method: string)
}
class NotConnectedError(ExecutorError):
"""The channel is not connected (yet, or any more)."""
def __init__(self, message: str = "executor channel is not connected") -> None: ...
class ClientStoppedError(ExecutorError):
"""The client was stopped, or closed with a terminal close code."""
def __init__(self, message: str = "client stopped") -> None: ...
var (
// ErrNotConnected is returned when a call is attempted before the channel opens.
ErrNotConnected = errors.New("bmaexecutor: executor channel is not connected")
// ErrClientStopped is returned after Stop or a terminal close code.
ErrClientStopped = errors.New("bmaexecutor: client stopped")
// ErrReplaced is Err after the harness closed with 4004: a newer
// connection for this executor is authoritative and this one must stop.
ErrReplaced = errors.New("bmaexecutor: executor connection was replaced (4004)")
// ErrReconnectExhausted is Err after a positive MaxReconnectAttempts
// failed; it wraps the last failure.
ErrReconnectExhausted = errors.New("bmaexecutor: executor reconnect attempts exhausted")
// ErrCredentialRejected is wrapped by the token request error when the
// token endpoint answers 401 or 403 (an invalid or revoked environment
// key or machine token). A reconnect does not retry it: the client ends
// with it as Err. A TokenSource may wrap it for the same effect.
ErrCredentialRejected = errors.New("bmaexecutor: executor credential rejected")
// ErrRegistrationRefused is Err after the platform refused the
// executor's registration maxRefusedRegistrations times in a row: the
// close 4002 "runtime registration refused" right after
// executor.register, or an executor.register error for the executor's
// capabilities. It is a configuration error (a machine-scoped executor
// must declare the process or agent capability) that reconnecting
// cannot fix. It wraps the last refusal.
ErrRegistrationRefused = errors.New("bmaexecutor: executor registration refused")
)
Harness errors
The harness end: the session ended, the executor was lost beforetool.result (the tool outcome is unknown), or the executor rejected session.assign.
export class SessionEndedError extends Error {
constructor()
}
export class ToolOutcomeUnknownError extends Error {
constructor()
}
export class AssignRejectedError extends Error {
constructor()
}
class SessionEndedError(ExecutorError):
"""A request on a session that has ended."""
def __init__(self) -> None: ...
class ToolOutcomeUnknownError(ExecutorError):
"""The executor was lost (lease expiry, executor.close, session ended, or a"""
def __init__(self) -> None: ...
class AssignRejectedError(ExecutorError):
"""session.assign answered accepted=false."""
def __init__(self) -> None: ...
var (
// ErrSessionEnded is returned for requests on a session that has ended.
ErrSessionEnded = errors.New("bmaexecutor: session ended")
// ErrToolOutcomeUnknown means the executor was lost (lease expiry,
// executor.close, session ended, or a restarted executor that no longer
// reports the session) before a tool.result arrived. The tool may or may
// not have run; the caller decides whether a retry is safe.
ErrToolOutcomeUnknown = errors.New("bmaexecutor: tool outcome unknown: executor lost before tool.result")
// ErrAssignRejected is returned when session.assign answers accepted=false.
ErrAssignRejected = errors.New("bmaexecutor: executor rejected session.assign")
)
Close codes
Which close codes end the client for good.export function isTerminalCloseCode(code: number): boolean
# Not in the Python SDK 1.3.0.
func CloseCode(err error) int
JSON-RPC error codes
| Code | Message |
|---|---|
-32700 | parse_error |
-32600 | invalid_request |
-32601 | method_not_found |
-32602 | invalid_params |
-32603 | internal_error |
-32000 | unauthorized |
-32001 | forbidden |
-32002 | not_found |
-32003 | lease_expired |
-32004 | timeout |
-32005 | canceled |
-32006 | payload_too_large |
-32007 | session_not_active |
-32008 | mcp_unavailable |
-32009 | executor_busy |
-32010 | unsupported_protocol |
-32011 | resource_unavailable |
-32012 | capability_unavailable |
-32013 | conflict |
Error data
| Name | Type | Required | Description |
|---|---|---|---|
retryable | boolean | no | Capacity or timeout failure the caller should retry with backoff. |
detail | string | no | |
capability | string | no | Missing capability for -32012, for example “tool:read” or “process.pty”. |
reason | string | no | Machine-readable cause; an open set that the harness passes through unchanged (process.start: the tool result error_code and the process state reason; turn.start: the session.error code). Recommended values: workspace_unavailable, workspace_boundary, workspace_read_only, session_rejected, local_confirmation_denied, local_confirmation_expired, spawn_failed / process_id_spec_mismatch for process.start, capability_missing for executor.register, and turn_inactive / forbidden / model_token_unavailable for model_token.refresh and turn_inactive / forbidden / tools_token_unavailable for tools_token.refresh (contract 1.4.0). The tool result error_code of a platform tool call (the platform tools endpoint, ToolErrorCode in the AsyncAPI x-bma-platform-tools) is an open set that also includes environment_unavailable, permission_denied, approval_required, approval_invalid, in_progress and idempotency_key_reused (contract 1.4.0). Receivers must accept values they do not know. |
terminal_code | string | no | bma.terminal.v1 error code for a failed terminal.* call. |
expected_sequence | integer | no | Agent session.event gap (-32013): the sequence the harness expects next. |
Close codes
| Code | Meaning |
|---|---|
4001 | token expired |
4003 | unsupported protocol |
4004 | replaced |
4005 | drained |