Skip to main content
Every SDK failure carries the same taxonomy: catch the base SailError for everything, or match a specific failure.
import sail

try:
    sb = sail.Sailbox.create(app=app, name="box")
    result = sb.exec("false", timeout=5).wait()
except sail.SailboxCreationError:
    ...  # creation failed
except sail.SailboxError:
    ...  # any other sailbox failure
import { Sailbox, SailboxCreationError, SailError } from "@sailresearch/sdk";

try {
  const sb = await Sailbox.create({ app, name: "box" });
  await (await sb.exec("false", { timeoutSeconds: 5 })).wait();
} catch (err) {
  if (err instanceof SailboxCreationError) {
    // creation failed
  } else if (err instanceof SailError) {
    // any other SDK failure
  }
}
use sail::error::SailError;
use sail::sailbox::types::CreateSailboxRequest;

match client
    .create_sailbox(
        &CreateSailboxRequest {
            app_id: app.id.clone(),
            name: "box".into(),
            ..Default::default()
        },
        /* timeout */ None,
    )
    .await
{
    Ok(sb) => {
        let _ = sb.exec_shell("false", Default::default()).await?.wait().await?;
    }
    Err(SailError::Creation { message, .. }) => eprintln!("creation failed: {message}"),
    Err(err) => eprintln!("{err}"),
}

The taxonomy

FailurePythonTypeScriptRust SailError::
Creation failedSailboxCreationErrorSailboxCreationErrorCreation
Custom image build failedImageBuildErrorImageBuildErrorImageBuild
Exec failedSailboxExecutionErrorSailboxExecutionErrorExecution
Sailbox gone (terminated)SailboxTerminatedErrorSailboxTerminatedErrorTerminated
Unknown exec requestSailboxExecRequestNotFoundErrorSailboxExecRequestNotFoundErrorExecRequestNotFound
Host machine lost mid-runSailboxWorkerLostErrorSailboxWorkerLostErrorWorkerLost
Unknown id / unexposed portLookupErrorNotFoundErrorNotFound
Auth failurePermissionErrorPermissionDeniedErrorPermissionDenied
Invalid argumentValueErrorInvalidArgumentErrorInvalidArgument
Missing guest fileFileNotFoundErrorFileNotFoundErrorFileNotFound
Readiness or build timeoutTimeoutErrorTimeoutErrorTransport (timeout)
Writing to a closed stdinBrokenPipeErrorBrokenPipeErrorBrokenPipe
Network/transport failureConnectionErrorTransportErrorTransport
Unexpected API responseRuntimeErrorApiErrorApi
Python uses builtins (LookupError, PermissionError, ValueError, FileNotFoundError, TimeoutError, BrokenPipeError, ConnectionError) where they are the natural fit; the SDK-specific classes all derive from sail.SailboxError, itself under sail.SailError.

Notable errors

Creation failed

Raised when Sailbox.create fails. When creation succeeded but SSH setup failed (with ssh=True), the message carries the new sailbox’s id so you can fetch it to retry enable_ssh or terminate it.

Host machine lost mid-run

The machine hosting your sailbox failed before the command finished. The command may have run only partially, and its output is gone. The run cannot be resumed: calling exec again starts it over from the beginning, so any side effects the partial run applied will happen again. The sailbox itself recovers automatically; you do not need to resume it.

Function errors (Python only)

SailboxFunctionError is raised when a @sail.function call fails while running in the sailbox. It carries the remote failure context:
AttributeTypeDescription
error_typestrRemote exception class name.
tracebackstrRemote traceback text.
stdoutstrCaptured remote stdout.
stderrstrCaptured remote stderr.
SailboxFunctionSerializationError is raised when a function payload or result cannot be serialized, or the remote function runtime cannot be prepared (including a Python major.minor version mismatch between your local interpreter and the sailbox’s python3). Both are subclasses of SailboxExecutionError.