Errors

Last updated

When Terminus refuses a request, it answers a problem: a small JSON object, the same shape everywhere, whose code says what went wrong. Branch on the code and the status, never on the words.

On this page⌄

What an error looks like#

Every answer that is not a success is application/problem+json, the IETF's standard error format (RFC 9457), with Terminus's code beside its own fields:

{
  "type": "https://terminus.build/docs/errors#version_conflict",
  "title": "Version conflict",
  "status": 409,
  "detail": "expected version 3, the record is at 4",
  "code": "version_conflict"
}
type
Where the code is explained: its row on this page.
title
A short summary of the code, the same every time it is answered.
status
The HTTP status, which a code always has.
detail
What happened this time, in words for people.
code
What went wrong, for a program to branch on.
details
Facts to act on, for the codes that carry any: the price to confirm, the service to connect, the version the data is at.

The SDK reads it for you: every refusal is a TerminusError whose code, title and details are the problem's, and whose message is its detail.

Terminus's OpenAI-compatible chat completions answer OpenAI's own error object instead, {"error": {"message", "type", "param", "code"}}, because OpenAI's clients read it. Its code is one of these.

Codes#

Every code, with its HTTP status and its title:

bad_request
400 · Bad request. The request is malformed: a path, query, header or body that is not valid, a field Terminus does not know, or a value out of range.
invalid_cursor
400 · Invalid cursor. The cursor is not one this list gave out for this query: it belongs to another list or another query, or it was changed. Ask for the first page again.
unauthorized
401 · Authentication required. No valid credential: the one the door takes (a session, a token, a client's secret or a signature) is missing or unknown, or someone who is not signed in asked for something that needs an account. detail says what the door takes, and how it is sent. A sign-in with the wrong email or password answers it too.
session_ended
401 · Session ended. The session was signed out or has expired: sign in again. An app stops and says so, and opening it again signs in.
forbidden
403 · Forbidden. Signed in, but not allowed: a role, a block, or what an app declared does not permit it.
grant_required
403 · Consent required. The person has not yet agreed to share this with the app. Ask for their consent rather than showing a plain refusal.
not_connected
403 · Service not connected. The service works in each person's own account, and this person has not connected it, or must connect it again. details names the service (service_id, address, name), how it connects (connect: sign_in or key) and why (reason: not_connected or reconnect). Nothing was sent.
collection_undeclared
403 · Collection not declared. The app's release does not declare this collection. An app declares every collection it uses in its schema.
not_found
404 · Not found. Nothing by that name or address is visible to the caller.
not_installed
404 · App not installed. The person has no installation of this app, so there is nothing to change.
method_not_allowed
405 · Method not allowed. The address exists, but not with this method: Allow lists the ones it takes.
conflict
409 · Conflict. The request conflicts with how things stand: a name already taken, a relation it would break, or an app updated since the session began.
version_conflict
409 · Version conflict. An expected version or hash no longer matches: read again, then retry with the new one.
idempotency_conflict
409 · Idempotency key reused. The Idempotency-Key was already used for a different request.
still_pending
409 · Still pending. A request with the same Idempotency-Key has not finished. Retry later with the same key.
lease_lost
409 · Lease lost. The job is no longer this worker's: its lease ran out and another worker took it over, or the job ended. Stop working on it: what this worker writes for it now is refused.
outcome_unknown
409 · Outcome unknown. The work was cut off after it had begun to send something out of Terminus, such as an email, a call to a service or an action on a desktop, so that may or may not have happened. It is not sent again: find out what happened before you try again.
update_required
409 · Update required. This release of the app is behind the data it writes, so it may read but not write until the app updates. details.data_version is the data's version, and details.kind is person or space.
data_migration_failed
409 · Data migration failed. The app's data did not pass one of its migrations: details.version names the migration, and details.message says what went wrong. Installing or updating the app is refused, and the installation stays where it was. Writing records is refused, and nothing of the write is stored, when the records of a write queued under an earlier release do not pass the migrations that release lacked, or when the person's or space's data it writes into has not passed a migration of the app's release; that data can still be read, and takes writes again once it passes.
client_update_required
426 · Client update required. This version of the Terminus CLI or desktop is older than the oldest Terminus accepts. detail says what to install, and details names the client (kind: cli or desktop), its version, the minimum and, for the desktop, the url it is downloaded from. Nothing was done.
payload_too_large
413 · Payload too large. A body, a field, or something fetched is larger than its limit.
unprocessable
422 · Unprocessable content. The request is well formed, but its content breaks a rule its data declares: fix the data, not the request.
refused
422 · Refused. An app's server or a service refused the request. details.code and details.status are what it answered, and the detail is its own words.
room_code_failed
422 · Room code failed. The room's code failed the step this message was handed to: it threw, answered what Terminus cannot keep or send, or ran past its time. Nothing of that step was kept or sent.
rate_limited
429 · Rate limited. Too many requests, or what the request changes is busy with another change. Wait as long as Retry-After says, when it says, then try again.
quota_exceeded
402 · Quota exceeded. The caller's credits, or storage, are used up for this.
price_confirmation_required
402 · Price confirmation required. A purchase that did not confirm its price, or confirmed another one. Nothing was charged: details.price_credits is the price due, so ask the person, then repeat the request with it.
url_not_allowed
400 · URL not allowed. Terminus will not reach this address: it is not a public http or https URL on a standard port.
upstream_failed
502 · Upstream failed. Something Terminus called for the request failed or answered badly: a website, a model's provider, a service, an app's server.
server_unavailable
503 · App server unavailable. The app's server cannot run right now. Try again shortly.
service_unavailable
503 · Service unavailable. Terminus is busy, or something it needs is not available. Try again shortly.
space_migrating
503 · Space migrating. A space's data is moving to a new version of the app. Try again after Retry-After.
deadline_exceeded
504 · Deadline exceeded. The request, or something it waited on, did not finish in time.
offline
503 · Offline. The device has no connection to Terminus, and this needs one. Nothing was sent: try again once it is back online.
not_read
503 · Not read. A read of a copy's pass that its request did not make: the request's budget was spent before it, or while it was being made. Nothing was read; the copy asks for it again in its next request.
not_implemented
501 · Not implemented. This host does not do this.
unsupported_in_dev
501 · Not available in terminus dev. terminus dev does not do this on a developer's machine; the published app does.
internal_error
500 · Internal error. Terminus failed, through no fault of the request. Trying again may work.
invalid_path
400 · Invalid path. The file path is not one Terminus can act on.
case_conflict
409 · Case conflict. A new name differs from one already there only in letter case: a Mac cannot keep both, so the second is refused.
destination_exists
409 · Destination exists. A move's destination already holds a file or a folder.
not_empty
409 · Folder not empty. A folder that may only be deleted while it is empty still holds a file.
file_too_large
413 · File too large. The file is too large to be read whole here: download it instead.
range_not_satisfiable
416 · Range not satisfiable. The Range asks for bytes the file does not have: Content-Range gives its size.
window_command
409 · Window command. This command runs in the app's window on the Terminus desktop, never through the API.

For your coding agent

https://www.terminus.build/docs/SKILL.md