Skip to content

Troubleshooting

View as Markdown

Building on Daytona means creating sandboxes, moving them through their lifecycle, and running code and services inside them. Those operations share a common surface: Daytona Dashboard, SDKs, CLI, and API, all backed by the sandbox model, organization, and resources.

When something does not behave as expected, the returned error and the sandbox record identify the cause. From there you retry the call, adjust the request, recover the sandbox, or create a new one. Account and organization issues often look like missing resources or permission failures before any sandbox call runs.

A sandbox moves from create through start and into later size and placement changes. Create selects a sandbox class and reserves resources from the regional pool. Provisioning then decides how that create is fulfilled: snapshot builds, warm pools, region availability, and resize.

Create and start allocate a sandbox from a snapshot or image and bring it to a running state. The request selects a sandbox class and reserves vCPU, memory, and disk from the organization’s regional pool. Each class has its own create rules and quota.

Symptom: Creating a container sandbox fails with 400 / DaytonaBadRequestError. The message typically reports that the total CPU, memory, or disk limit is exceeded for the region.

Cause: Container sandboxes draw from the organization’s compute and storage pool in that region. Stopped container sandboxes free CPU and memory, but they still occupy disk quota until they are archived or deleted. A full disk quota can therefore block create even when CPU and memory look available.

Solution:

  1. Check current usage in Limits ↗
  2. Stop sandboxes you are not using to free CPU and memory
  3. Archive or delete stopped container sandboxes to free disk quota
  4. Upgrade your tier if the pool itself is too small

See create sandboxes and disk quota.

Provisioning covers how a create is fulfilled after the sandbox class is chosen: warm pools, snapshot builds, region availability, and resize of reserved resources.

Symptom: A warm pool exists for the snapshot, but create still takes a cold-start path. The new sandbox works, yet it does not come from the pool and start time is higher than expected. Separately, GET or POST /api/warm-pools may return 404.

Cause: Warm claim is exact. The create request must match the pool on snapshot, region, the snapshot’s default CPU, memory, and disk, the default OS user (daytona), and must not set custom environment variables, volumes, or secrets. Any mismatch skips the pool. The warm pools API is also gated: when warm pools are not enabled for the organization, those endpoints return 404 even though they appear in the docs.

Solution: Align the create request with the pool, or accept a cold create when you need custom env, volumes, secrets, or resources. If the API returns 404, use the Dashboard Warm Pool controls when available, or contact support@daytona.io to enable warm pools for your organization. See warm pools.

Account issues sit outside the sandbox lifecycle. They come from which organization you are working in, and from whether your membership and assignments allow the action. Quotas, API keys, and sandboxes are scoped per organization. For API key and HTTP auth failures, see authentication.

Symptom: Sandboxes, snapshots, API keys, or limits you expect are missing in the Dashboard or API. Creates succeed, but the new sandbox appears under a different organization than your team uses. Quotas look empty or unexpectedly low compared with another organization.

Cause: Every user has a personal organization, and may also belong to one or more collaborative organizations. Each organization has its own sandboxes, API keys, and resource quotas. The Dashboard shows only the organization selected in the sidebar. An API key is bound to the organization that issued it, so a key from your personal organization cannot list or manage resources in a collaborative organization.

Solution:

  1. In Daytona Dashboard ↗, open the organization dropdown at the top-left of the sidebar and select the organization you intend to use
  2. Confirm the sandbox, key, or limit under that organization
  3. For SDKs, CLI, or API calls, use an API key created in that same organization

See organizations and personal vs collaborative.

Symptom: You are signed in and the correct organization is selected, but create, delete, or admin actions fail with 403 / DaytonaForbiddenError, or the Dashboard keeps resources read-only. A teammate invited you, yet you still cannot create sandboxes or keys in that organization.

Cause: Collaborative organizations use roles and assignments. Owners have full access. Members need assignments such as Developer to create sandboxes and keys; Viewer alone is read-only. An invitation also does nothing until it is accepted, and access to that organization’s quotas requires a new API key issued after you join.

Solution:

  1. Open Invitations ↗ and accept any pending invitation for the organization
  2. Ask an organization owner to grant the assignments you need (for example Developer to create sandboxes and keys)
  3. After joining, create an API key in that organization and use it for SDK, CLI, and API calls

See members, invitations, and authentication.

Once a sandbox is started, it keeps a lifecycle state, accepts inbound and outbound traffic, and runs processes. Failures here show up in the sandbox record, preview or VNC sessions, network calls, process APIs, and rate-limit responses.

State covers whether a started sandbox stays usable: recovery from error, automated lifecycle stops and deletes, and operations that depend on the sandbox class.

Symptom: The sandbox is no longer usable and reports state as error. Calls that expect a started sandbox fail, and errorReason describes what went wrong during start or restore, such as a timeout while creating, starting, or pulling a snapshot.

Cause: The sandbox failed to reach a healthy started state. Some of these failures are recoverable: Daytona can restore the sandbox from its last successful backup. Others are not, and the sandbox must be replaced.

Solution:

  1. Read sandbox.errorReason and sandbox.recoverable
  2. If recoverable is true, call sandbox.recover() and wait until the sandbox is started
  3. If it is not recoverable, delete the sandbox and create a new one from a snapshot

See recover sandboxes.

from daytona import Daytona, ListSandboxesQuery
daytona = Daytona()
for sandbox in daytona.list(ListSandboxesQuery(is_recoverable=True)):
sandbox.recover()

Access covers reaching services inside a started sandbox and driving work through it: preview, VNC, network policy, process execution, and rate limits.

Symptom: A browser or HTTP client cannot reach a service through the sandbox preview URL. The response is 401 or 403 even though the sandbox is started and the port is listening.

Cause: Preview authentication depends on the URL type, and the two token kinds are not interchangeable. A standard preview URL expects the token in the x-daytona-preview-token header, and that token is reset when the sandbox restarts. A signed preview URL embeds the token in the URL itself; it cannot be sent as a header, and it stops working when it expires or when signing keys are rotated.

Solution: Use the matching auth method for the URL type. Refresh standard tokens after restart. Check signed URL expiry. See preview.

The Daytona SDKs raise subclasses of DaytonaError for API, daemon, proxy, and transport failures. Catch the precise class or catch DaytonaError for a general handler.

from daytona import Daytona, DaytonaError, DaytonaNotFoundError, DaytonaRateLimitError
daytona = Daytona()
try:
sandbox = daytona.get("missing-sandbox")
except DaytonaNotFoundError as e:
print(e.status_code, e.message)
except DaytonaRateLimitError as e:
print(e.headers.get("retry-after-sandbox-create"))
except DaytonaError as e:
print(e.status_code, e.code, e.source, e.message)

Symptom: API calls return 401 / DaytonaAuthenticationError or 403 / DaytonaForbiddenError, sometimes with a message about an invalid authentication context, even when an API key looks valid.

Cause: The key is missing, revoked, scoped to a different organization, or lacks the permission required for the operation. SDKs and the API bind requests to an organization; using a key from one org while targeting another, or omitting required organization context, produces auth failures. Dashboard sign-in issues (SSO, email alias requirements) are separate from API key auth.

Solution:

  1. Create or rotate a key in API Keys ↗ for the organization you intend to use
  2. Set DAYTONA_API_KEY (or the SDK config equivalent) to that key
  3. Confirm the key has the permissions required for the call
  4. For wrong-organization or membership issues in the Dashboard, see account
  5. For SSO or account sign-in problems in the Dashboard, contact support@daytona.io

See API keys and organizations.

AttributeDescription
messageHuman-readable description. Varies per response; do not match on exact text.
status_codeHTTP status when the error came from a Daytona service. None / unset for pure client-side failures.
codeMachine-readable code from the response envelope when present (for example FILE_NOT_FOUND).
sourceOriginating service: DAYTONA_API, DAYTONA_DAEMON, or DAYTONA_PROXY. Unset when the response has no envelope.
headersResponse headers (includes rate-limit headers on 429). Empty for client-side errors.
StatusSDK classWhen it is raisedTypical response
400DaytonaBadRequestErrorMalformed or invalid requestFix parameters; do not retry as-is
401DaytonaAuthenticationErrorMissing or invalid credentialsRefresh API key / auth; do not retry with the same key
403DaytonaForbiddenErrorAuthenticated caller lacks permissionCheck API key scopes and organization membership
404DaytonaNotFoundErrorResource does not existCreate or look up a different ID; do not retry
408DaytonaTimeoutErrorRequest timed outRetry idempotent reads; decide whether to recover/create
409DaytonaConflictErrorConflicts with current resource stateRefresh state, then decide
410DaytonaGoneErrorResource existed but is permanently goneDo not retry the same operation; recreate if needed
422DaytonaUnprocessableEntityErrorWell-formed request that is semantically invalidFix parameters; do not retry as-is
429DaytonaRateLimitErrorOrganization rate limit exceededWait Retry-After-{throttler}, then retry with backoff
500DaytonaInternalServerErrorUnexpected server failureRetry with backoff; escalate if persistent
502DaytonaBadGatewayErrorUpstream dependency rejected or dropped the requestRetry with backoff
503DaytonaServiceUnavailableErrorService temporarily refusing trafficRetry with backoff
504DaytonaTimeoutErrorGateway timed outRetry idempotent reads; decide whether to recover/create
CodeSDK classHTTP classMeaning
GIT_AUTH_FAILEDDaytonaGitAuthFailedErrorAuthentication (401)Git credentials rejected by the remote
GIT_REPO_NOT_FOUNDDaytonaGitRepoNotFoundErrorNot found (404)Git repository does not exist
GIT_BRANCH_NOT_FOUNDDaytonaGitBranchNotFoundErrorNot found (404)Git branch does not exist
GIT_BRANCH_EXISTSDaytonaGitBranchExistsErrorConflict (409)Branch name already exists
GIT_PUSH_REJECTEDDaytonaGitPushRejectedErrorConflict (409)Push rejected (non-fast-forward / stale ref)
GIT_DIRTY_WORKTREEDaytonaGitDirtyWorktreeErrorConflict (409)Worktree has uncommitted changes
GIT_MERGE_CONFLICTDaytonaGitMergeConflictErrorConflict (409)Merge conflicts need resolution
FILE_NOT_FOUNDDaytonaFileNotFoundErrorNot found (404)Filesystem entry not found
FILE_ACCESS_DENIEDDaytonaFileAccessDeniedErrorForbidden (403)Insufficient filesystem permissions
INVALID_FILE_PATHDaytonaInvalidFilePathErrorBad request (400)Invalid filesystem path (TypeScript SDK)
FILE_READ_FAILEDDaytonaFileReadFailedErrorInternal server (500)Filesystem read failed (TypeScript SDK)
LSP_SERVER_NOT_INITIALIZEDDaytonaLspServerNotInitializedErrorBad request (400)LSP server must be started first
PROCESS_EXECUTION_TIMEOUTDaytonaProcessExecutionTimeoutErrorTimeoutProcess exceeded its execution timeout
PROCESS_NOT_FOUNDDaytonaProcessNotFoundErrorNot found (404)Process is not running
SESSION_ENDEDDaytonaSessionEndedErrorGone (410)Shell session has ended
COMMAND_ALREADY_COMPLETEDDaytonaCommandAlreadyCompletedErrorGone (410)Shell command already finished
A11Y_UNAVAILABLEDaytonaA11yUnavailableErrorService unavailable (503)Accessibility (AT-SPI) bus not reachable
RECORDING_STILL_ACTIVEDaytonaRecordingStillActiveErrorConflict (409)Recording still running; stop it first
RECORDING_FFMPEG_NOT_FOUNDDaytonaRecordingFfmpegNotFoundErrorService unavailable (503)ffmpeg not installed; required for recording

Full reference: Python SDK errors, TypeScript SDK errors, Go SDK errors.

SDK classWhen it is raisedTypical response
DaytonaConnectionErrorCannot connect or the connection drops mid-requestRetry with backoff
DaytonaConnectionTimeoutErrorTransport connect/read timeoutRetry with backoff; raise client timeout
DaytonaInvalidArgumentErrorSDK rejected arguments locally before sending a request (TypeScript)Fix arguments; do not retry as-is
DaytonaTimeoutErrorClient wait deadline on lifecycle helpers (for example start)Raise timeout or recover/recreate
import time
from daytona import Daytona, DaytonaRateLimitError
daytona = Daytona()
def create_with_retry(max_retries: int = 5):
for attempt in range(max_retries):
try:
return daytona.create()
except DaytonaRateLimitError as e:
if attempt == max_retries - 1:
raise
retry_after = e.headers.get("retry-after-sandbox-create")
delay = int(retry_after) if retry_after else 2 ** attempt
time.sleep(delay)
from daytona import Daytona
daytona = Daytona()
sandbox = daytona.get("my-sandbox")
# Wait up to 40 seconds for recover to reach started
if sandbox.recoverable:
sandbox.recover(timeout=40)
# Wait up to 60 seconds for start
sandbox.start(timeout=60)