DocsErrors

Errors

Both SDKs map every HTTP status and RPC code they recognise to a typed error. Transport failures and a few internal invariants surface as the language's plain Error / Exception, so keep a branch that rethrows anything you do not recognise. The names are identical in the two languages except for the suffix: Error in TypeScript, Exception in Python.

Catch an error

Import the class you care about and catch it by type. SandboxError is the base for most of them, so catch it last.

import { Sandbox, SandboxError, TimeoutError } from '@impello/sdk'

const sandbox = await Sandbox.create('base')

try {
  await sandbox.commands.run('sleep 120', { timeoutMs: 5000 })
} catch (err) {
  if (err instanceof TimeoutError) {
    console.error('the command ran out of time', err.message)
  } else if (err instanceof SandboxError) {
    console.error('the sandbox refused the call', err.message)
  } else {
    throw err
  }
} finally {
  await sandbox.kill()
}

The error classes

TypeScriptPythonExtendsThrown when
SandboxErrorSandboxExceptionErrorThe base class, and the fallback for any status or RPC code with no mapping of its own
TimeoutErrorTimeoutExceptionSandboxErrorThe sandbox timed out, the request timed out, or a long-running call passed its own timeout
InvalidArgumentErrorInvalidArgumentExceptionSandboxErrorThe sandbox rejected an argument, or the SDK rejected one before sending it
NotEnoughSpaceErrorNotEnoughSpaceExceptionSandboxErrorThe sandbox's disk is full
NotFoundErrorNotFoundExceptionSandboxErrorDeprecated. A resource was not found. Catch the two classes below instead
FileNotFoundErrorFileNotFoundExceptionNotFoundErrorA file or directory inside the sandbox does not exist
SandboxNotFoundErrorSandboxNotFoundExceptionNotFoundErrorThe sandbox does not exist, or is no longer running
RateLimitErrorRateLimitExceptionSandboxErrorYou are being rate limited
TemplateErrorTemplateExceptionSandboxErrorThe template is too old for the call, or an alias or tag call was rejected
GitUpstreamErrorGitUpstreamExceptionSandboxErrorgit push or git pull ran on a branch with no upstream. Deprecated with the git module; run git through commands.run instead
CommandExitErrorCommandExitExceptionSandboxErrorA command exited non-zero
AuthenticationErrorAuthenticationExceptionErrorThe key is missing, malformed, or the server rejected it
GitAuthErrorGitAuthExceptionAuthenticationErrorgit clone, push or pull failed to authenticate with the remote. Deprecated with the git module; run git through commands.run instead
BuildErrorBuildExceptionErrorA template build failed. TypeScript only in practice
FileUploadErrorFileUploadExceptionBuildErrorUploading the build context failed. TypeScript only in practice

VolumeError / VolumeException is exported too, but nothing throws it: neither SDK ships a volume client. BuildException and FileUploadException are exported by the Python SDK for parity in the same way. The Python SDK covers sandboxes only and has no template builder, so nothing raises either of them there; the template builder is TypeScript-only.

No error carries a retryable flag. RateLimitError is the only one whose message tells you a retry is worth trying.

HTTP and RPC mapping

Three transports produce errors, and each has its own map.

The control plane

Calls to https://api.sandbox.impello.ai — create, connect, list, kill, setTimeout, pause, snapshots, metrics, template builds.

StatusError
401AuthenticationError. The message contains Unauthorized, please check your credentials. (prefixed with the status code in Python), and the server's own sentence is appended after a hyphen when it sends one
429RateLimitError. The message contains Rate limit exceeded, please try again later (prefixed with the status code in Python), and the server's own sentence is appended after a hyphen when it sends one
404SandboxNotFoundError from getInfo, getMetrics, setTimeout, updateNetwork, pause, createSnapshot and connect
anything elseSandboxError, and its message is the status code, a colon and the server's own sentence. The template-build calls raise BuildError in its place, and the alias and tag calls raise TemplateError

kill and deleteSnapshot are the exceptions: a 404 from either returns false rather than throwing, because the thing you asked to delete is gone either way.

The sandbox over HTTP

Filesystem reads, writes and uploads go to the sandbox itself.

StatusError
400InvalidArgumentError
401AuthenticationError
404NotFoundError, and FileNotFoundError on filesystem calls
429RateLimitError
502TimeoutError — this is what a sandbox that has already timed out looks like
507NotEnoughSpaceError
anything elseSandboxError

The sandbox over RPC

Commands, the terminal and directory watches run over an RPC stream, so they carry status codes rather than HTTP statuses.

CodeError
InvalidArgumentInvalidArgumentError
UnauthenticatedAuthenticationError
NotFoundNotFoundError, and FileNotFoundError on filesystem calls
ResourceExhaustedRateLimitError
UnavailableTimeoutError — the sandbox timed out
CanceledTimeoutError — the request was cancelled in flight. In TypeScript the request timeout fired, or you aborted the signal you passed in. In Python the server or a proxy cancelled it, for example a sandbox that was paused or shut down
DeadlineExceededTimeoutError — the call's own timeout was exceeded
anything elseSandboxError

Three different failures therefore arrive as TimeoutError: the sandbox is gone, your request timeout fired, or the call's own timeout fired. Read the message — the TypeScript message names the option to change. In Python a request timeout arrives as DeadlineExceeded over RPC, and as a TimeoutException naming request_timeout on the HTTP calls. If the connection is dropped mid-request, the SDK probes the sandbox's health. It raises TimeoutError only once the probe confirms the sandbox is gone; otherwise the transport error reaches you unchanged. See Timeouts.

Commands and directory watches are the exception to the Unavailable row above. An Unavailable on the first stream event raises SandboxNotFoundError in TypeScript, with the message Sandbox is probably not running anymore. Catch that class as well as TimeoutError around commands.run and files.watchDir. The Python SDK maps UNAVAILABLE to TimeoutException in every case, so the two SDKs differ here.

Command exits

commands.run waits for the process and throws when it exits non-zero. The error carries the whole result, so you do not need to re-run anything to see what happened.

import { Sandbox, CommandExitError } from '@impello/sdk'

const sandbox = await Sandbox.create('base')

try {
  await sandbox.commands.run('cat /home/user/missing.txt')
} catch (err) {
  if (err instanceof CommandExitError) {
    console.error(err.exitCode, err.stderr, err.stdout)
  }
} finally {
  await sandbox.kill()
}

CommandExitError exposes exitCode, error, stdout and stderr (exit_code, error, stdout, stderr in Python). A background command throws the same error from its handle's wait(). See Run commands.

Authentication

The SDKs check the shape of your key before any request leaves the process. A key the SDK cannot recognise as a key at all raises AuthenticationError immediately, without a round trip. The current prefix is imp_ followed by hex characters. Whether the key is a good key is the server's answer, and that arrives as 401.

CauseError
No key in IMPELLO_API_KEY and none passed inAuthenticationError, before any request
Key is not imp_ plus hexAuthenticationError, before any request
An older key, minted under the prefix Impello used before it moved to its ownPython raises AuthenticationException before any request, with a message that names the old prefix. TypeScript accepts the shape and the server answers 401. See Migrate
Key is well-formed but the server rejects itAuthenticationError from the 401

Keys are created and read at dashboard.impello.ai/keys. See API keys. In TypeScript, set IMPELLO_VALIDATE_API_KEY=false to skip the local shape check. The Python SDK always performs it, and its validate_api_key option has no effect.

Refused creates

A create can be refused for reasons that have nothing to do with your code. No credit left, a spend ceiling you set on your own team, or a plan limit. The plan limits are how many sandboxes you may run at once, how fast you may start them, and how long a sandbox may live. A sandbox bigger than your plan allows — vCPU, memory or disk — is refused the same way. A create is also refused, never queued, when there is no capacity free right now.

There is no dedicated error class for any of these, and they all surface the same way. Read the message rather than branching on the type: the class you get depends on the status the API returns. A 429 from any cause becomes RateLimitError, and a status with no mapping of its own becomes SandboxError, whose message is the status and the server's own sentence.

Top the team up or raise the ceiling at dashboard.impello.ai/billing; the plan limits themselves are on Limits and pricing. Retrying does not help while the reason is your credit, your ceiling or a plan limit. Back off and retry a capacity refusal or a RateLimitError: both clear on their own. Impello publishes one address, legal@impello.ai. Write there when a refusal is not explained by your plan or your credit; there is no other support channel yet.

Old templates

TemplateError on a working call means the sandbox's agent is older than the feature you asked for. Rebuild the template and the error goes away.

CallNeeds
Creating a sandbox0.1.0
Recursive files.watchDir0.1.4
getMetrics0.1.5
metadata on files.write0.6.2
includeEntry on files.watchDir0.6.3
allowNetworkMounts on files.watchDir0.6.4

A sandbox created from a template older than 0.1.0 is killed for you before the error is raised. See Build a custom template.

Python names

Every class above that the Python SDK raises is exported from the top-level impello package, with the same name and the same base class, ending in Exception instead of Error:

from impello import (
    AuthenticationException,
    CommandExitException,
    FileNotFoundException,
    GitAuthException,
    GitUpstreamException,
    InvalidArgumentException,
    NotEnoughSpaceException,
    NotFoundException,
    RateLimitException,
    SandboxException,
    SandboxNotFoundException,
    TemplateException,
    TimeoutException,
)

The async API raises exactly the same exceptions as the sync one.

Next: Limits and pricing.