Skip to main content

Exceptions and error handling

Every exception the SDK throws lives in the Revolution\Copilot\Exceptions namespace. They surface in two ways: some are held on the session result and thrown when you call throw(), and others are thrown immediately, for example by RPC calls.

Session errors and timeouts

With sendAndWait() and Copilot::run(), a session error or timeout is not thrown on the spot. Instead, the exception is held on the returned SessionEvent. Just like Laravel’s Http and Process, calling throw() raises the held exception. When there is no error, throw() does nothing, so you can keep chaining methods.
To check success without throwing, use failed() and successful(). See SessionEvent for details.

SessionTimeoutException

Held when the wait for session.idle (the response completing) times out. Set the timeout with the timeout argument of sendAndWait(). When you omit it, the copilot.timeout config value is used (60 seconds by default).

SessionErrorException

Held when the session returns an error through a SESSION_ERROR event. The message contains the error returned by the runtime.

JsonRpcException

Thrown immediately when the CLI returns a JSON-RPC error for an RPC call. Read the JSON-RPC error code from the code property and any data attached to the error from the data property.

SessionFsSqliteTransactionFailure

Use this exception when you implement a SessionFs SQLite provider. You don’t catch it. Instead, you throw it from the provider’s transaction() to tell the runtime how the failure should be classified. Set the classification with errorClass:
  • Fatal (default): an unrecoverable failure
  • BusyOrLocked: use only when SQLite returned BUSY/LOCKED before commit and the transaction was rolled back
  • PostCommitAmbiguous: the outcome after commit cannot be determined
Any other exception thrown from transaction() is reported as fatal.

StrayRequestException

Thrown by the testing fake when you send a request that has no matching fake registered. If you hit it unexpectedly, you forgot to register a fake for that request. See Testing for how to use fakes.
Last modified on November 15, 2026