Errors
Errors
The error envelope
Plane errors are JSON with a stable machine-readable code:
| HTTP | error |
Meaning |
|---|---|---|
| 400 | invalid_body |
Missing/malformed body (e.g. no data object, no file part) |
| 400 | invalid_document |
Payload fails the schema it is validated against |
| 400 | unsupported_item |
Operation not defined for the slot’s kind (e.g. writing or deleting through a files slot) |
| 400 | invalid_target |
The legacy items/{kind}/{target} target could not be decoded |
| 401 | unauthenticated |
No valid caller behind the token |
| 403 | partner_token_required |
A first-party (non-partner) token was presented |
| 403 | unknown_client |
The token’s client is no longer registered |
| 403 | organization_suspended |
Your owning organization is suspended |
| 403 | connection_inactive |
The connection is revoked, withdrawn, or expired |
| 403 | verb_not_granted |
The slot does not carry the verb this operation needs |
| 403 | delete_refused |
The platform protects this document from deletion |
| 403 | subject_item_readonly |
Delegated write or delete on a family member’s slot |
| 403 | participant_ineligible |
The named party may not answer this subject: wrong relation, already cast in another role, the subject’s one seat is taken, or the user no longer manages the company (409 on a delegated company write) |
| 403 | limit_reached |
The user’s plan allows no more family-member vaults |
| 404 | not_found |
Ungranted, foreign, malformed, or nonexistent — deliberately one answer |
| 404 | participant_unknown |
The alias names nobody the user may answer with, or a different party than the resource belongs to |
| 409 | ambiguous_item |
The (kind, target) pair matches several slots / records — use slot ids |
| 409 | slot_conflict |
A concurrent fill changed the slot’s grants — re-list and retry |
| 409 | participant_conflict |
A concurrent fill cast this participant or subject differently — re-list and retry |
| 409 | subject_kind_unsupported |
The act does not apply to this subject’s kind (company founding not enabled) |
| 413 | too_large |
The upload exceeds the per-file cap (32 MiB by default); nothing written |
| 422 | participant_required |
A subject slot was filled without saying who |
| 422 | participant_not_allowed |
A participant was named on a recipient slot |
| 423 | sealed |
The user’s vault key could not be opened right now; see sealed keys |
| 423 | org_sealed |
The record’s key is your organization’s to open and no member is signed in |
| 500 | server_error |
Transient server failure — safe to retry |
Info
Read 404 as “nothing for you here”, never as “does not exist.” The same
answer covers an item the user declined to share, an id from another user, and
an id that was never real. Probing teaches nothing — by design.
One 403 has a different body: a security-gate refusal (the token lacks the
scope the route needs) answers with the platform’s GraphQL-style envelope —
{"errors":[{"message":"…","extensions":{…}}]}. Retrying does not help; the
connection needs that scope.
Unavailable records
Not every refusal is a status code. When a slot is served, a record the user
can no longer hand over arrives inside the 200 with status: "unavailable" and a reason, so one dark record never hides the rest of a
slot:
reason |
Meaning | What to do |
|---|---|---|
participant_ineligible |
The user can no longer speak for the party that answered (left the company, lost the Manager role) | Show it; the grant and any kept copy stand, and it serves again if standing returns |
record_unreadable |
This server could not produce the record right now | Retry later; not consent withdrawn, so keep the party |
Read status before type on every record, and treat an unknown status as
unavailable. See Reading & writing data.
Sealed keys
Geena opens the user’s vault key on the server whenever a call needs it, so a
seal is rare. Neither 423 is consent withdrawn: keep the connection and its
parties.
423 sealed: the user’s vault key could not be opened right now. The entitlement is real. Retry, or ask the user to sign in to Geena.423 org_sealed: the key is your organization’s, and it warms when a member of your organization signs in (to the dashboard, or through the organization-access ceremony). No action by the user is needed; retry once a member is in.