Errors
The Shardflux error envelope and every error code and details.reason the API and the cell gateway return, with HTTP status, meaning and what to do.
The error envelope
Every non-2xx response from the application API and from the cell gateway has the same body:
{
"error": {
"code": "rate_limited",
"message": "Too many requests. Try again later.",
"request_id": "req-9b0e1d2c3f4a5b6c7d8e9f00",
"retryable": true,
"details": { "retry_after_seconds": 42 }
}
}| Field | Meaning |
|---|---|
code |
A closed set of snake_case codes (below). Branch on code and details.reason, never on message. |
message |
Safe, human-readable English. Show it when you have nothing better for a code. |
request_id |
The same value as the X-Request-Id response header. Include it when you contact support. |
retryable |
Whether the same request may succeed later. |
operation_id |
Optional. The lifecycle operation that caused the error; poll it with GET /v1/operations/{id}. |
details |
Optional. Per-code details, most often reason, plus fields such as field, names or limit. |
Treat a code or reason you do not know as a generic error: show message and use retryable. New reasons can appear
at any time within /v1.
A few responses do not have this body: a 502, 503 or 504 from a load balancer can carry an HTML page, and a
service shutting down can answer 503 with a different JSON shape. Treat them as retryable. The SDKs raise
ShardfluxProtocolError for them.
Retrying
| Situation | Retry? |
|---|---|
GET or HEAD, and retryable: true or status 429, 502, 503 or 504 |
Yes, with exponential backoff, honouring Retry-After. |
A mutation sent with an Idempotency-Key, after a retryable error or a network failure |
Yes, with the same key and the same body. |
A mutation without an Idempotency-Key |
Not automatically: the request may have taken effect. |
retryable: false |
No. Change the request, the plan or the credentials first. |
409 with an operation_id (operation_in_progress, workspace_not_running, workspace_busy) |
Wait for the operation, then retry. |
Cell 409 stale_epoch |
Once, after getting a new tool token. |
| An execution of a file-first workspace, after a network failure or a retryable error | Yes, with the same execution_id and body: the command runs at most once. |
409 conflict with revision_mismatch or tree_revision_mismatch |
Not as it is. Read the current state, then send a new request. |
The TypeScript and Python SDKs apply these rules for you.
Application API codes
Codes returned by https://api.shardflux.dev/v1:
| Code | HTTP | Retryable | Meaning | What to do |
|---|---|---|---|---|
bad_request |
400 | no | Malformed JSON, or Content-Type: application/json with an empty body. |
Fix the request. Omit the header on a request without a body. |
token_invalid |
400 | no | An emailed link (email verification, password reset, email change) is invalid, expired or already used. | Request a new link. |
unauthenticated |
401 | no | The Authorization header is missing or not Bearer, or the API key or a person's CLI session is malformed, unknown, revoked or expired. |
Check SHARDFLUX_API_KEY; create a new key in the console if it was revoked. For a session, sign in again (shard auth login). |
invalid_credentials |
401 | no | Sign-in (/v1/auth) with a wrong email or password, or a wrong two-factor or recovery code. The same answer for an account that does not exist. |
Check the credentials. Repeated wrong codes lock the second factor (429, mfa_locked). |
entitlement_required |
402 | no | Your plan does not allow this start, build or volume (see reasons). | Change the plan or settle the payment. |
allowance_exhausted |
402 | no | A compute allowance of your plan is used up and overage is off or paused, or overage reached its spend cap (see reasons). details has reason, allowance, meter, unit, used, included, resets_at, plan, exhausted and spend_cap. |
Act on details.reason. Do not retry in a loop. |
quota_exceeded |
403 | no | A plan limit was reached. details.limit names it, with limit_value and current (see limits). |
Suspend or delete something, or upgrade. |
forbidden |
403 | no | The key may not do this: a tool it lacks (details.denied_tools, permitted_tools), an owner or admin action, an action only a person can take ("API keys cannot perform this action."), or a reason below. |
Use a key with the permission, sign in as a person (shard auth login), or ask an owner or admin. |
mfa_required |
403 | no | A person's session is still waiting for its second factor. | Complete the sign-in: POST /v1/auth/mfa/challenge, or shard auth mfa --code <code>. |
email_unverified |
403 | no | A person's session before the email address is verified. | Verify it with the emailed link (shard auth verify-email '<link>'). |
step_up_required |
403 | no | A sensitive action (exports, deletions, email and two-factor changes) without a password check in the last 10 minutes. | Step up (POST /v1/auth/step-up, or shard auth step-up), then retry. |
not_found |
404 | no | The resource does not exist, or it is outside the key's project. The two are not distinguished. | Check the id, key or slug. |
conflict |
409 | depends | The resource is in a state that refuses the request; details.reason says which (see reasons). |
Act on the reason. |
payload_too_large |
413 | no | The request body is too large. | Send less. |
unsupported_media_type |
415 | no | The body is not JSON. | Send Content-Type: application/json. |
validation_failed |
422 | no | The request is invalid: details.issues (schema checks: path and message) or details.field and details.reason (see reasons). |
Fix the named field. |
idempotency_mismatch |
422 | no | The Idempotency-Key was already used with a different request within 24 hours. |
Use a new key for a new request. |
rate_limited |
429 | yes | Too many requests. Retry-After gives the seconds to wait, also in details.retry_after_seconds. |
Wait, then retry. |
internal_error |
500 | yes | An unexpected server error. | Retry safe requests; report the request_id if it persists. |
dependency_unavailable |
503 | yes | A dependency is temporarily unavailable (a reason may say which). | Retry with backoff. |
capacity_pending |
503 | yes | Not returned as an HTTP error: it is an operation state (see Operation errors). | Keep waiting for the operation. |
stale_epoch |
409 | yes | Returned by the cell gateway (below). | Get a new tool token. |
Requests with an API key never receive token_invalid, invalid_credentials, mfa_required, email_unverified or
step_up_required: they come from /v1/auth and from requests with a person's CLI session (Authorization: Bearer sfu_...; see Authentication). The console's own routes also use
csrf_failed, which /v1 never returns.
Cell gateway codes
Codes returned by a workspace's cell_endpoint (exec, files, terminals, processes, git, browser):
| Code | HTTP | Retryable | Meaning | What to do |
|---|---|---|---|---|
bad_request |
400 | no | Invalid query or path parameters, or malformed JSON or unknown fields. | Fix the request. |
unauthenticated |
401 | no | No tool token, or it is malformed, expired or revoked (details.reason: revoked_watermark, revoked_workspace, revoked_api_key, revoked_api_key_tools). |
Get a new tool token and retry once. |
forbidden |
403 | no | The token is for another workspace or lacks the tool (details.tool); or a named secret is not available (secret_not_available). |
Request a token with the tool; check the key's permissions. |
not_found |
404 | no | The workspace is unknown or deleted, or a file does not exist (on a file-first workspace also any path outside /home/user, outside_tree_root). |
Stop, or fix the path. |
conflict |
409 | depends | stale_endpoint (the workspace moved to another cell), a session_id or Idempotency-Key reused for a different request (operation_id_reused), an interrupted attempt whose outcome is unknown (operation_interrupted), legacy_disk_layout, guest_feature_unavailable, and the reasons of file tools and hosts and file-first workspaces. |
stale_endpoint: read the workspace again and use its new cell_endpoint. Interrupted: reattach to the session instead of re-running. |
stale_epoch |
409 | yes | The token was issued before the workspace's latest suspend, resume or move. | Get a new tool token and reconnect with your last offsets. |
workspace_not_running |
409 | yes | The workspace is suspended or not on a host. The call was not executed. A suspended workspace's file reads are answered from its disk while a host still holds it; offline_unavailable and offline_budget say that such a read could not be. |
Resume it (or open the key), then retry with a new token. |
workspace_busy |
409 | yes | A lifecycle operation holds the workspace (operation_id; details.operation_kind; details.tool_gate: read_only or closed; or details.reason: workspace_fenced), or an execution of a file-first workspace runs (execution_in_progress, details.execution_id). The call was not executed. |
Wait for the operation or the execution, then retry. During read_only, reads still work. |
validation_failed |
422 | no | Invalid parameters (paths, a relative cwd (invalid_cwd), modes, signals, terminal size, a reserved sfstart. session id, env_collision), or a patch that does not apply (edit_not_found, edit_ambiguous, edit_not_text, patch_invalid). |
Fix the request. |
payload_too_large |
413 | no | The body, stdin (over 1 MiB), file write or patch (over 7 MiB) is too large (details.max_bytes). |
Send less. |
range_not_satisfiable |
416 | no | The Range is not a single bytes=start-end, or starts past the end of the file (details.size). |
Request within the size. |
rate_limited |
429 | yes | The workspace is at a resource limit, or there were too many secret resolutions. Retry-After gives the seconds to wait. |
Back off and retry idempotent calls. |
dependency_unavailable |
503 | yes | The workspace host or a gateway dependency is temporarily unavailable, or the disk changed during a read of a sleeping workspace (offline_changed). |
Retry with backoff. |
service_unavailable |
503 | yes | The gateway has too many concurrent streams, or is draining. Also: the workspace's host has no room to wake it right now (host_capacity), a wake failed (wake_failed), or no host can run an execution now (no_execution_host). Nothing was executed. |
Retry after Retry-After, or a second. |
timeout |
504 | yes | The workspace did not answer in time. | Retry idempotent calls. For exec, reattach to the session instead of starting it again. |
internal_error |
500 | no | An unexpected gateway error. | Report the request_id. |
The cell enum also contains capacity_pending; the gateway never returns it.
Reasons
details.reason refines a code. The tables list the reasons a request with an API key can meet; the last
one adds those of a person's session.
402 entitlement_required
| Reason | Meaning | What to do |
|---|---|---|
no_plan |
The organization has no active plan. | Choose a plan in the console. |
limits_missing |
The plan lacks a limit the request needs (details.missing). |
Upgrade. |
not_included |
The plan does not include this feature (shared volumes). | Upgrade. |
payment_past_due |
A payment is overdue and the grace period ended (details.grace_until). New starts are refused; running workspaces are not affected. |
An owner or billing member updates the payment method. |
unpaid |
The subscription is unpaid. | As above. |
operator_hold |
New starts are on hold for the organization. | Contact support. |
402 allowance_exhausted
New opens, resumes and forks are refused, and the organization's running workspaces are suspended with their files, memory and processes kept. Nothing is deleted. See Overage.
| Reason | Meaning | What to do |
|---|---|---|
allowance_used |
The plan's CPU-hours or RAM GiB-hours allowance is used up, and overage is off or not available on the plan. | Wait for resets_at, upgrade, or have an owner or billing member turn on overage in the console. |
overage_paused |
The allowance is used up, and overage is on but paused while a plan payment is past due. | An owner or billing member pays the invoice or updates the payment method. |
spend_cap_reached |
Overage charges reached the spend cap for this billing period. | Wait for resets_at, have an owner or billing member raise the cap (up to the plan price), or upgrade. |
details field |
Meaning |
|---|---|
reason |
One of the reasons above. |
allowance, meter, unit |
The first used-up allowance (cpu_hours or ram_gib_hours), its meter (cpu_seconds or memory_gib_seconds), and the unit of used and included. |
used, included |
This period's usage and the plan's allowance, in unit. |
used_meter_units, included_meter_units |
The same in meter units (CPU-seconds or GiB-seconds). |
exhausted |
Every used-up allowance, each with allowance, meter, used, included and unit. |
resets_at |
The end of the billing period, when the allowances and the spend cap reset. |
plan |
The plan key, for example developer. |
spend_cap |
null when overage is not available on the plan. Otherwise cap_minor (the configured cap, null if never set), effective_cap_minor (the cap that applies: cap_minor limited to the plan price, or the plan price when no cap is set), charges_minor (overage charged this period) and currency. Amounts are in minor units (cents). |
403 quota_exceeded
details.limit |
Meaning |
|---|---|
concurrent_workspaces |
Running workspaces allowed by the plan (open, resume and fork count). Suspend or delete one. |
concurrent_template_builds |
Unfinished template builds. Wait for one to finish. |
shared_volumes_max |
Shared volumes of the organization. |
shared_volume_gib_max |
The size of one shared volume. |
volume_attachments_per_workspace |
Volumes attached to one workspace. |
403 forbidden
| Reason | Meaning |
|---|---|
template_dev_mode_role |
Drafts and test instances (their creation, lifecycle calls and tool tokens) need an owner, an admin or an API key with a tool permission. |
secret_not_available |
An exec or terminal start names a secret (details.names) this workspace may not use; nothing was started. Also returned for starts while a bound secret's status is not_allowed. |
404 not_found
| Reason | Meaning |
|---|---|
draft_not_found |
The template has no draft. |
version_not_found |
No such template version. |
path_not_found |
The path is not in the version's file tree (details.path). |
checkpoint_not_found |
No such checkpoint of the workspace. |
draft_state_not_found |
No such draft state. |
package_not_found |
No package with that name in the ecosystem. |
log_not_available |
The build has no full log yet; use the log tail on the build. |
log_expired |
The build's full log is past its retention. |
409 conflict
| Reason | Retryable | Meaning | What to do |
|---|---|---|---|
operation_in_progress |
yes | Another lifecycle operation runs on the workspace (active_operation_id, active_operation_kind). |
Wait for it, then retry. |
workspace_not_running |
yes | A tool token was requested while the workspace is suspending, or while a resume that was asked for has not started yet; or a browser stream while it is not running (observed_state, desired_state). A suspended workspace does get a tool token: the cell answers it only the reads of the workspace's disk. |
Open or resume the workspace, then request the token. |
workspace_deleted |
no | The workspace is deleted; keys are never reused. | Use a new key. |
not_running |
no | Suspend, or suspend when idle, of a workspace that is not running. | Refresh the workspace. |
already_running, not_suspended |
no | Resume of a workspace that is not suspended. | Nothing to do. |
not_snapshottable, not_forkable, not_resettable |
no | The workspace is not running or suspended. | Refresh the workspace. |
key_in_use |
no | The fork's target key is taken. | Choose another key. |
lifetime_mismatch |
no | The key is open with another lifetime (lifetime, requested_lifetime). |
Omit lifetime, or use another key. |
session_lifetime |
no | A session workspace cannot be suspended, now or when idle, and has no idle policy. | Close it, or fork it to keep its state. |
not_session |
no | Close of a persistent workspace. | Suspend or delete it instead. |
legacy_disk_layout |
no | Reset, save as template and changes need a layered workspace. |
Use a layered workspace. |
layout_unsupported |
no | The template version needs a disk layout that is not available here, or it cannot run a file-first workspace (disk_layouts). |
Use another template version. |
not_supported_for_mode, mode_mismatch |
no | A call that the workspace's mode does not have, or a reopen with the other mode (see file-first workspaces). | Use what the mode offers, or omit mode. |
template_not_layered |
no | A draft's base is not layered-capable. | Choose another base. |
draft_exists |
no | The template already has a draft (workspace_id). |
Use that draft. |
draft_stale |
no | The template got a newer version since the draft was opened (latest_version, draft_base_version). |
Start a new draft from the latest version. |
build_in_progress |
yes | Another build of the template is unfinished (build_id). |
Wait for it, then publish. |
build_finished |
no | Cancel of a build that already finished. | Nothing to do. |
file_list_unavailable |
no | The version has no file list (published before file lists existed). | Open a draft or test instance to see its files. |
file_list_indexing |
yes | The file list is still being indexed. | Retry shortly. |
guest_feature_unavailable |
no | The workspace's template cannot do this (for example list changes). | Use a newer template version. |
package_index_unavailable |
pip: yes; apt: no | The base has no apt index, or the pip name index is not built yet. | Type the package name; the build checks it. |
template_archived, version_archived |
no | The template or version is archived. | Use another template or version. |
name_taken |
no | A secret with that name exists in the scope. | Choose another name, or rotate the existing secret. |
secret_deleted |
no | The secret is deleted. | Create it again. |
concurrent_rotation |
yes | Another rotation of the secret ran at the same time. | Retry. |
version_mismatch |
no | Egress policy or spend policy update with a stale If-Match (current_version). |
Read the policy again and re-apply. |
name_in_use |
no | A live volume of the project has that name. | Choose another name. |
volume_attached |
no | Delete of a volume that is still attached (attachments). |
Detach it, or delete with force. |
volume_creating, volume_not_available |
yes while creating | The volume is not available yet (volume_state). |
Wait until it is available. |
volume_not_shared |
no | The volume belongs to another project. | Use a volume of this project. |
already_attached, detach_in_progress, attach_in_progress |
attach_in_progress: yes |
The volume is already attached with another path or mode, or an attach or detach is still running. | Detach first, or retry shortly. |
mount_path_conflict |
no | The mount path equals or nests with another mount of the workspace. | Choose another path. |
Two retryable 409s have no reason: a request whose Idempotency-Key is still in progress, and an open of a key that
another open is creating at the same moment. Retry the same request (with the same key).
422 validation_failed
Workspaces, inputs and secrets:
| Reason | Meaning |
|---|---|
reserved_key_prefix |
Workspace keys starting with sf: are reserved. |
mode_not_available |
This deployment does not offer file-first workspaces (field: mode). |
not_supported_for_mode |
lifetime: "session" for a file-first workspace, which is always persistent (field: lifetime). |
confirm_destructive_required |
Reset needs {"confirm_destructive": true}. |
secret_not_available |
A secret name to bind is unknown or not usable by this workspace (details.names); nothing changed. |
env_collision |
A bound secret has the name of a template environment variable or text input (details.name). |
input_required |
A required input is missing (details.names, details.kind). |
input_unknown |
The template declares no input with that name (details.names). |
input_invalid |
An input value is not a string, is a secret input, is over 4096 bytes, or contains CR, LF or NUL. |
egress_widening |
A workspace egress policy allows more than the template's egress ceiling (outside). |
reserved_prefix, nul_character, too_large |
Secret names starting with SHARDFLUX_, a value with a NUL byte, or a value over the size limit. |
Workspace tools (the cell gateway):
| Reason | Meaning |
|---|---|
invalid_cwd |
An exec, execution or terminal start named a cwd that is not an absolute path (or has a NUL byte, or is over 4096 bytes); details.field is cwd. Relative paths are not resolved: the message names the absolute path the cwd likely means, e.g. use "/home/user/app". Nothing ran. |
Templates and builds:
| Reason | Meaning |
|---|---|
invalid_recipe |
The recipe does not match the recipe v2 schema (details.field). |
invalid_path, invalid_package, invalid_host |
A path, package name or host in the recipe is invalid (details.field). |
invalid_settings |
settings do not match the settings schema, or settings.defaults was given together with defaults. |
base_not_found, base_archived, base_not_published, architecture_not_supported |
The recipe's base cannot be used. |
base_not_layered |
A recipe v2 build needs a layered-capable base. |
base_required |
A draft of a template without a published version needs base. |
language_unavailable |
The base does not offer that language or version (available). |
language_conflict |
The base already has another version of the language. |
too_many_files, too_many_steps, too_many_hosts, recipe_too_large |
The recipe is over a size limit (limit). |
platform_owned_path |
A file destination is owned by the platform. |
upload_required |
A file entry still names a local from path: upload it and send upload: "sha256:<hex>". |
upload_missing |
The organization has no upload with that SHA-256. |
upload_digest_mismatch |
The same SHA-256 was announced with another size, or the bytes do not match. |
upload_too_large |
An upload is over 5 GiB. |
extra_hosts_without_auto, allow_hosts_without_allowlist, allowlist_empty |
The build network settings are inconsistent. |
services_unsupported |
The base's guest agent cannot run services; remove settings.services or use a newer base. |
invalid_defaults |
An idle timeout without lifetime: "session". |
update_policy_not_available |
update_policy: "auto" is not available. |
too_many_acknowledged_findings |
More than 200 acknowledged scan findings. |
platform_template_slug, reserved_template_slug, slug_not_supported_by_builder |
The slug cannot be used for an organization template. |
Egress policy validation returns every problem in details.issues, each with path, reason and message.
Spend policy (overage and its spend cap, changed by an owner or billing member; details.field names the field):
| Reason | Meaning |
|---|---|
overage_unavailable |
The plan has no overage (Free, or no active subscription). |
spend_cap_required |
Turning overage on needs a spend cap. |
spend_cap_below_minimum |
The cap is below $1 (min_minor). |
spend_cap_above_plan_price |
The cap is above the plan price (max_minor). |
spend_cap_below_charges |
Overage already charged more than that this period (charges_minor). Turning overage off is always allowed. |
503 dependency_unavailable
| Reason | Meaning |
|---|---|
package_search_unavailable, package_index_loading |
Package search is temporarily unavailable. Retry. |
uploads_not_configured |
Template uploads are not available in this environment. |
build_log_bucket_not_configured, signing_failed |
The full build log cannot be served right now; use the log tail on the build. |
File tools, parking and hosts
Reasons of the cell gateway for search, patches and reads of sleeping workspaces and for parked workspaces:
| Code and reason | Retryable | Meaning | What to do |
|---|---|---|---|
409 conflict revision_mismatch |
no | A patch's expected_revision is not the file's current revision (details.current_revision, absent for a missing file). Nothing changed. |
Read the file again and redo the edit. |
422 validation_failed edit_not_found |
no | An edit's old text does not occur in the file (details.index, counting from 0). Nothing changed. |
Fix that edit. |
422 validation_failed edit_ambiguous |
no | An edit's old text occurs more than once (details.index). Nothing changed. |
Include more surrounding text, or set replace_all. |
422 validation_failed edit_not_text |
no | The file is not UTF-8 text, so edits cannot apply. | Replace it with content. |
422 validation_failed patch_invalid |
no | The patch does not have exactly one of edits and content. |
Fix the request. |
409 workspace_not_running offline_unavailable, offline_budget |
yes | A read of a suspended workspace could not be answered from its disk. | Resume the workspace and read again. The SDKs, the CLI and the MCP server do. |
503 dependency_unavailable offline_changed |
yes | The disk changed during a read of a sleeping workspace, because it started running. | Retry: the running workspace answers. |
503 service_unavailable host_capacity |
yes | The workspace's host has no room to wake it right now (Retry-After). The call was not executed. |
Retry after Retry-After. |
503 service_unavailable wake_failed |
yes | Waking the parked workspace failed; its state is intact. The call was not executed. | Retry. |
409 workspace_busy workspace_fenced |
yes | A lifecycle operation is taking over the workspace. The call was not executed. | Wait for the operation, then retry. |
409 conflict host_feature_unavailable |
no | The workspace runs on a host that does not have this call yet (details.feature: file_search or file_patch); reads and stats there come without revisions. It lasts until the workspace runs on an upgraded host. |
Use another way: grep in a command instead of a search, a read and a write instead of a patch. |
File-first workspaces
Reasons of the API and the cell gateway for file-first workspaces:
| Code and reason | From | Retryable | Meaning | What to do |
|---|---|---|---|---|
409 conflict not_supported_for_mode |
API, cell | no | The call does not exist for the workspace's mode (details.mode, details.operation): suspend, resume, snapshot, fork, reset, save as template, volumes, idle policies, exec sessions, terminals, processes, git, browser, changes or keepalives of a file-first workspace, or reading an execution of a processful one. |
Use what the mode offers. |
422 validation_failed not_supported_for_mode |
API, cell | no | lifetime: "session" when opening a file-first workspace, or execution_id / output_limit_bytes in an exec of a processful workspace. |
Leave the field out. |
409 conflict mode_mismatch |
API | no | The key belongs to a workspace of the other mode (mode, requested_mode). A mode never changes. |
Omit mode, or use another key. |
422 validation_failed mode_not_available |
API | no | This deployment does not offer file-first workspaces. | Use a processful workspace. |
409 conflict layout_unsupported |
API | no | The template version has no layered disks, which executions need (disk_layouts). |
Use a layered template version. |
409 conflict tree_revision_mismatch |
cell | no | If-Match names another revision than the tree's (details.current_tree_revision). Nothing changed. |
Read what changed, then retry with the new revision. |
404 not_found, 422 validation_failed outside_tree_root |
cell | no | A read (404) or a change (422) of a path outside /home/user (details.tree_root). |
Use a path under /home/user. |
409 workspace_busy execution_in_progress |
cell | yes | An execution runs (details.execution_id); a second execution or a file change must wait. |
Retry when it has ended. The SDKs and the CLI wait. |
409 conflict execution_id_reused |
cell | no | The execution id was already used for a different request. | Use a new id for a new command. |
503 service_unavailable no_execution_host |
cell | yes | No host has room for the execution now (Retry-After). Nothing ran, and the id stays unused. |
Retry with the same id. The SDKs and the CLI do. |
An execution that ended failed or lost published nothing. Its result carries error with code, message,
retryable (whether a new execution may succeed) and details.reason, for example exec_failed_to_start,
lease_expired, host_unreachable, host_restarted, tree_moved, blob_missing, blob_corrupt,
layout_unsupported or guest_feature_unavailable.
With a person's session
Account actions on /v1 need a person's CLI session (sfu_..., from /v1/auth or shard auth login); an API key
gets 403 forbidden for them. These are the reasons they add to the tables above:
| Code and reason | Meaning | What to do |
|---|---|---|
409 conflict subscription_exists |
Checkout for an organization that already has a subscription. | Change plans in the billing portal (POST .../billing/portal-sessions, shard billing portal). |
409 conflict checkout_superseded |
A concurrent checkout request for another plan replaced this one. | Retry. |
409 conflict subscription_active, checkout_pending |
Organization deletion while a subscription is active (billing_state, current_period_end) or a Checkout session is open (checkout_id, expires_at). |
Cancel the subscription in the billing portal, or let the checkout finish or expire. |
409 conflict organization_ownership |
Account deletion while you are the only owner of an organization with other members, or its only member (details.organizations). |
Transfer ownership of those organizations, or delete them. |
409 conflict last_owner |
A role change or removal would leave the organization without an owner. | Make someone else an owner first. |
409 conflict concurrent_invitation |
An invitation to the same address is being created at the same moment. | Retry. |
409 conflict export_expired |
The data export's download is past its expiry (expires_at). |
Create a new export. |
409 conflict export_too_large |
An audit export would exceed its row limit (max_rows, matched_rows_at_least). |
Narrow the time window or the filters. |
422 validation_failed plan_not_purchasable |
Checkout for a plan that cannot be bought (field: plan_key). |
Choose a plan from GET /v1/billing/catalog. |
429 rate_limited mfa_locked |
Too many wrong two-factor codes (retry_after_seconds). |
Wait, or reset the password by email. |
Operation errors
A failed operation (state: failed or canceled) carries error: {code, message, retryable, details}. The SDKs raise
it as OperationFailedError (errorCode, retryable).
error.code |
Retryable | Meaning | What to do |
|---|---|---|---|
capacity_unavailable |
yes | No host could admit the start within 15 minutes of its creation. Nothing was started; a suspended workspace stays suspended. details: reason, waited_seconds, deadline_seconds, required. |
Send the same request again later. |
invalid_resources |
no | The start needs more CPU, memory or disk than any host has (details.reason: exceeds_host_class, required, host_class, exceeded). |
Open with smaller caps. |
startup_failed |
yes | A start command or service of the template failed (details.reason: startup_failed, service_not_ready, secrets_unavailable, secret_not_available, guest_feature_unavailable). The workspace keeps running for inspection; startup names the step, exit code and output tail. |
Fix the cause; the next open runs the failed step again. |
layout_unsupported |
no | The host cannot run the template's disk layout. | Use another template version. |
dependency_failed |
no | The operation depended on one that failed (for example a draft capture behind a test instance). | Check the other operation. |
layer_capture_failed |
no | Capturing a draft state or a template source failed. | Retry the capture. |
Operation state_reason values are progress, not errors: no_ready_host while capacity_pending (waiting for a
host), template_downloading while running (the host is fetching the template).
Template builds from a workspace or a draft report failure.code on the build: source_unavailable (the capture
failed or the checkpoint is gone), resource_limit (details.limit: template_org_bytes_max or
template_file_entries_max), scan_failed (the credential scan found secrets: the paths are listed; build again with
acknowledged_scan_findings), compatibility_failed and publish_failed.
Client errors
The clients add their own errors for failures that never reached the API:
- TypeScript SDK:
ExecStartError(0.10.0+: a command that could not start; aShardfluxApiErrorwithexec_failed_to_start),OperationFailedError,OperationTimeoutError,ShardfluxProtocolError,ToolArgumentError,CheckoutTimeoutError(0.9.0+) and the template errors (reference).NotSupportedForModeErrorandTreeRevisionMismatchError(0.9.0+) areShardfluxApiErrors fornot_supported_for_modeandtree_revision_mismatch; the SDK raises the first before sending a call the mode does not have (local: true). - Python SDK: the same classes under
ShardfluxError, withCheckoutTimeoutError,NotSupportedForModeErrorandTreeRevisionMismatchErrorfrom 0.5.0, andExecStartErrorfrom 0.6.0 (reference). - CLI: exit codes and local codes such as
usage,interruptedand (0.5.0+)checkout_endedandexecution_failed(an execution that endedfailedorlost, exit 6) (reference). - MCP server:
invalid_arguments,workspace_pinned,timeout,operation_failedand others. An error result carries the refusal'sreason, and from 0.4.0 ahintfor the file-first and host refusals (reference).