# Errors

> **Preview.** This page describes the interface WIRK launches with. The hosted service is in private staging and access is by invitation. What is live today: /docs/index.md#what-is-live-today

A refusal is the normal [envelope](/docs/http-api.md#the-envelope) with `"ok": false` and one or more problems. Nothing is applied when a write is refused.

```json
{"ok": false,
 "text": "Not applied w-8b1d07e2c4 · basis_changed: 5c1e7a90 is at r5; you read r3\n  Fetch it again (query 5c1e7a90), check that your change still applies, and resend under a new request_id.",
 "errors": [{"code": "basis_changed", "message": "5c1e7a90 is at r5; you read r3",
             "field": "expect.5c1e7a90", "requested_id": "item_5c1e7a90…",
             "hint": "Fetch it again (query 5c1e7a90), check that your change still applies, and resend under a new request_id."}],
 "notices": [], "page": {"complete": true, "next_cursor": null}, "timing_ms": {"total": 1.1}}
```

| Field | Meaning |
|---|---|
| `code` | Stable, for programs |
| `message` | What happened |
| `hint` | The next step, often a runnable command |
| `choices` | Allowed values, or the records an ambiguous reference could mean |
| `field` | Where in the request, for example `operations[1].data.to` or `fields.priority` |
| `input_index` | Which operation of a write |
| `requested_id` | The record the problem is about |

## Codes

| Code | HTTP | What to do |
|---|---|---|
| `unauthenticated` | 401 | Run `wirk login`: it checks this machine's token and shows the digest your administrator registers |
| `not_authorized` | 403 | You lack the role for this; ask an administrator. Also: you proposed this, so someone else accepts it |
| `no_wirkspace` | 403 | Your token works but you are in no wirkspace; ask an administrator to add you |
| `not_available` | 404 | No record you can read has that ID. Use an ID from a card or a fetch |
| `method_not_allowed` | 405 | Use the method in [HTTP API](/docs/http-api.md#routes) |
| `basis_changed` | 409 | Something changed since you read it. Fetch it again, check your change still applies, resend under a new `request_id` |
| `request_conflict` | 409 | That `request_id` was used with a different body. Resend the identical body to read its receipt, or use a new ID |
| `stale_cursor` | 409 | The cursor belongs to a different request. Repeat the original request exactly |
| `upload_too_large` | 413 | The file is over `max_upload_bytes` (5 GiB by default); split or compress it |
| `invalid_budget`, `budget_too_small` | 400 | `max_bytes` is out of range or too small for one entry; raise it |
| `too_many_views` | 429 | Too many `wirk show` links in 24 hours; the message says when the next can be made |
| `database_unavailable` | 503 | The service could not reach its database; nothing was applied. Try again shortly |
| `files_unavailable` | 503 | File storage is unavailable or not configured for this account; try again later |
| `views_unavailable` | 503 | `wirk show` is not switched on for this service |
| `upload_incomplete` | 422 | The bytes are not in storage yet. Put them (ask for a fresh upload link if the first expired), then confirm again |
| `upload_mismatch` | 422 | The stored bytes' size, SHA-256 or encryption differ from what you declared. Upload again |
| `choose_wirkspace` | 422 | Your token has several wirkspaces; pass one of the `choices` as `workspace_id` |
| `ambiguous_ref` | 422 | A short ID or title matches several records; pick one of the `choices` |
| `no_match` | 422 | Nothing has that ID or exact title; try `about=` or `text=` |
| `unknown_filter` | 422 | Use a filter from the `choices` |
| `unknown_enum_field`, `unknown_enum_option` | 422 | Use a field or value from the `choices` |
| `invalid_enum_selection`, `required_enum_missing`, `enum_not_applicable` | 422 | Fix the field value as the message says |
| `unknown_owner` | 422 | The owner must be a member; the `choices` list them. `me` means you |
| `likely_duplicate` | 422 | The work already exists; use the named item, or resend with `allow_duplicate_of` and a `reason` |
| `reason_required` | 422 | Give a `reason`: completing work needs its evidence; proposing and archiving need a reason |
| `reason_too_long` | 422 | A reason is at most 2,048 characters |
| `requires_review` | 422 | Context is maintained by someone else, or added by administrators: propose the change instead |
| `invalid_context` | 422 | A context rule was broken: level, state, one organization item per wirkspace, no work or files on context, at most 8,000 characters, or a maintainer who cannot edit |
| `invalid_link` | 422 | A link rule was broken, for example `requires` outside work, or a prerequisite added to completed work (reopen it first) |
| `work_relationship_exists` | 422 | Remove the links that depend on it first, such as `requires` links or work contributing to an initiative |
| `invalid_view` | 422 | A `wirk show` bound was exceeded, or the time zone is unknown |
| `invalid_input`, `unknown_field` | 422 | The request's shape is wrong; `field` says where |

## Notices

Notices accompany a successful answer:

- `replayed`: answered from the stored receipt; nothing was applied again.
- `context_ignored`: the `Wirk-Context` header was invalid and was ignored.
- `context_parsed`: how a context item's text was read into parts.
- `context_long`: a context item is over its authoring target.

## Errors from the clients

The CLI and MCP server print the service's refusals exactly as worded. They report these themselves, each with the address tried and the next step:

| Code | Meaning |
|---|---|
| `not_configured` | WIRK is not set up on this machine. Run `wirk login` |
| `service_unavailable` | The service could not be reached (DNS, refused, TLS, timeout). Check the network, then `curl https://api.wirk.life/health` |
| `outcome_unknown` | A write or review got no answer after one automatic resend. Run the same command again with the printed `--request-id`, or `wirk query receipt=ID` |
| `missing_route` | The service answered 404 without an envelope: it does not have that route yet |
| `unexpected_redirect` | The service answered with a redirect; nothing was sent there |
| `service_error` | An answer that is not from WIRK, such as an edge error page |
| `storage_failed` | Storage refused an upload or download link; nothing was stored. Run the same command again with the printed `--request-id` |
| `insecure_token_file` | A token file is readable by others, is a link, or belongs to another user. `chmod 600` it |

Example:

```
Error outcome_unknown: https://api.wirk.life did not answer (timed out after 60 s); request w-3f9a2c41d0 may or may not have been applied.
  Run the same command again with --request-id w-3f9a2c41d0: it applies once or returns the stored receipt. Or: wirk query receipt=w-3f9a2c41d0
```
