---
title: "Errors"
url: https://services.dev/docs/reference/errors
captured: [brand-credential.txt, hand-to-person.txt, legal-refused.txt, legal-region.txt, people-refusals.txt, period-tabs.txt]
---
# Errors

URL: https://services.dev/docs/reference/errors

> Every code a call or check can return, with its category, its HTTP status and the operations that return it. A buyer’s or member’s code renders on the brand’s own /docs/errors/<code>.

52 codes a call can answer with, and 31 gates `check` can fail. Every refusal takes one shape, on all four surfaces: [Answers](https://services.dev/docs/api/answers.md) covers it, and `next`, the call that fixes it when one can.

## One refusal

```txt
magic values: none

$ curl http://localhost:8787/jobs/job_0000
← 404 · {
  "type": "EMPTY",
  "category": "invalid_request",
  "code": "not_found",
  "reason": "No job job_0000.",
  "param": "id",
  "next": null,
  "doc_url": "http://localhost:8787/docs/errors/not_found",
  "request_id": "req_c7PJaH",
  "simulated": true
}
```

Every refusal’s `type` is its AXP envelope, the word an agent dispatches on: `EMPTY` for a 404, an id nothing has, and `BLOCKED` for every other no. Its `category` is the kind of no, and says whether the same call can ever work.

## Every code, by category

Each code renders on the brand’s own site at `/docs/errors/<code>`, the `doc_url` its refusal carries, in the brand’s words. A code more than three calls can answer shows their count; [Operations](https://services.dev/docs/reference/operations.md) names, for each call, every code it can answer.

### `invalid_request` codes

| Code | HTTP | Operations | Means | Fix |
|---|---|---|---|---|
| <a id="input_invalid" />`input_invalid` | 422 | 36 operations | The order doesn't match the Service's input. | Fill the fields next.fill names, then send next. |
| <a id="not_found" />`not_found` | 404 | 58 operations | Nothing has that id. | Read /.well-known/agents.json for the Services, and use the id an answer returned. |
| <a id="route_unknown" />`route_unknown` | 404 | — | No operation is served at that HTTP method and path. | Read /openapi.json for every route, or /llms.txt for every operation. |
| <a id="body_invalid" />`body_invalid` | 400 | 46 operations | The body isn't JSON. | Send a JSON object with content-type: application/json. |
| <a id="version_unknown" />`version_unknown` | 400 | every operation | This brand doesn't serve that Services-Version. | Leave Services-Version out, or send one the answer names. |
| <a id="policy_invalid" />`policy_invalid` | 422 | `service.order`, `job.again`, `job.policy` | A policy value is out of bounds; the reason lists each. | Fix the values next.fill names. |
| <a id="evidence_required" />`evidence_required` | 422 | `clock.satisfy` | A clock closes on evidence on the record: a file, or a receipt or file the job already holds. | Send evidence: a file \{ url, name \}, or the id of a receipt (rcp_…) or the sha256 of a file the job holds. |
| <a id="event_id_required" />`event_id_required` | 422 | `event.inbound` | An event that mints a job on a subscription is one occurrence: it needs your id for it. | Send id: your own id for the event, such as the notice number. The same id sent again answers replayed: true and mints nothing more. |
| <a id="defects_required" />`defects_required` | 422 | `task.send_back` | A send-back names its defects: what is wrong, for the step it returns to. | Send defects, and to: the step it returns to, when it is not the one before. |
| <a id="memo_required" />`memo_required` | 422 | `task.decline` | A decline carries a reasoned memo, which only the client reads. | Send memo: why you decline. The decline is paid, and never scored. |
| <a id="evidence_missing" />`evidence_missing` | 422 | `task.complete` | The step completes on evidence items that are not all present. | Capture each missing item the refusal names, then complete again. |

### `conflict` codes

| Code | HTTP | Operations | Means | Fix |
|---|---|---|---|---|
| <a id="key_reused" />`key_reused` | 409 | 15 operations | That key was already sent with a different body. | Send next: the same call under a fresh key. To get the first answer back, resend it with its original body. |
| <a id="not_waiting" />`not_waiting` | 409 | `job.send_back`, `job.approve` | The job isn't waiting on a person. | Read the job with get_job. Accept or send back a delivered one. |
| <a id="not_delivered" />`not_delivered` | 409 | `job.accept`, `job.send_back` | Only a delivered job can be accepted or sent back. | Wait for delivery with get_job. |
| <a id="not_cancelable" />`not_cancelable` | 409 | `job.cancel` | The job is already delivered. Send it back instead. | Send it back with a note, and the AI redoes it. |
| <a id="nothing_to_redo" />`nothing_to_redo` | 409 | `job.send_back` | This job's work came from another Service that already delivered, so there's nothing to redo. | Accept the job as delivered. |
| <a id="end_not_allowed" />`end_not_allowed` | 409 | `job.end`, `job.approve`, `task.attest` | The job can't end that way now. | Read the reason. |
| <a id="not_terminal" />`not_terminal` | 409 | `job.again` | Only an ended job is ordered again. | Wait for it to end, or cancel. |
| <a id="period_taken" />`period_taken` | 409 | `service.order`, `job.again` | A job of this Service already holds the subject's period: one live or ended job per period. | Send next: the follow-on the job's end offers, such as an amendment, ordered from that job. A canceled job frees its period. |
| <a id="evidence_used" />`evidence_used` | 409 | `clock.satisfy` | That evidence closed another clock already: evidence closes one clock. | Send what proves this clock itself. next reads the clock the evidence closed. |
| <a id="clock_closed" />`clock_closed` | 409 | 4 operations | The clock is closed: it was satisfied, or its owner chose at its date. | Read the clock with GET /clocks/:id: a closed clock takes no more calls. A recurring one brings its next occurrence when it is satisfied, and stays open. |
| <a id="clock_not_due" />`clock_not_due` | 409 | `clock.choose` | The owner chooses at the clock's date. | Read the clock with GET /clocks/:id: its rungs and its date. The choice opens at clock.due. |
| <a id="clock_moved_on" />`clock_moved_on` | 409 | `clock.ack`, `clock.satisfy`, `clock.choose` | The clock is at another occurrence than the due you sent: it moved, or recurred, since you read it. | Send next: the same call, with due set to the date the clock is at now. Read it first if you need to decide again. |
| <a id="date_passed" />`date_passed` | 409 | `job.approve`, `task.attest` | The step is barred: a hard date on the job passed unsatisfied, and nothing moves it. | Read the clock with GET /clocks/:id: its owner chooses among its lapse options. A charge that waits on a barred step never releases. |
| <a id="clock_behind" />`clock_behind` | 409 | `test_clock.advance` | A test clock only moves forward, and that time is behind it. | Send to: a time after frozen_at, or a span. Sending the time it reads already changes nothing. |
| <a id="clock_advancing" />`clock_advancing` | 409 | `test_clock.advance` | The test clock is advancing already: one advance at a time. | Wait for the advance in flight, then read the clock and send yours. |
| <a id="task_taken" />`task_taken` | 409 | 9 operations | Another member holds this Task, or has it offered to them first. | Read your feed for the Tasks offered to you now. |
| <a id="needs_direction" />`needs_direction` | 409 | `task.attest` | A member declined, and only the client's direction moves the job on: another member, or an end. | Hand the client the direct ask in next; nothing else moves it. |
| <a id="not_contestable" />`not_contestable` | 409 | `task.contest` | There is no send-back on this attested work to contest, or it is already contested or ruled. | Read the Task: a contest answers a send-back your attested work received, once. |
| <a id="job_ended" />`job_ended` | 409 | 9 operations | The job has ended, for good. | Order it again with next. |
| <a id="question_open" />`question_open` | 409 | `task.message` | A question to the client is out already, and their reply comes through the thread. | Wait for the reply, or post a note: a note expects none. |
| <a id="ask_expired" />`ask_expired` | 410 | `ask.complete`, `ask.reissue` | This ask expired. | Hand over the new link in next. |
| <a id="ask_voided" />`ask_voided` | 410 | `ask.complete`, `ask.reissue` | This link no longer works: used, reissued or voided. | Use the link in next. |
| <a id="signature_void" />`signature_void` | 409 | `ask.complete` | What was signed changed past its tolerance. | Sign the new version in next. |

### `authentication` codes

| Code | HTTP | Operations | Means | Fix |
|---|---|---|---|---|
| <a id="key_missing" />`key_missing` | 401 | 38 operations | No key: send Authorization: Bearer sk_test_…. | Send the key dev printed, as Authorization: Bearer sk_test_…. |
| <a id="key_invalid" />`key_invalid` | 401 | 38 operations | That key isn't one of this brand's. | Send the key dev printed, as Authorization: Bearer sk_test_…. |

### `blocked` codes

| Code | HTTP | Operations | Means | Fix |
|---|---|---|---|---|
| <a id="needs_a_person" />`needs_a_person` | 403 | 32 operations | A person approves and signs, in the app. A key or a tool never can. | Wait for the job with get_job; it carries on once the person acts. |
| <a id="merits_not_yours" />`merits_not_yours` | 403 | `job.policy` | Only the client sets the merits. | Ask the client to set it through their own call, POST /jobs/:id/policy, with their key. |
| <a id="needs_the_owner" />`needs_the_owner` | 403 | `clock.ack`, `clock.satisfy`, `clock.choose` | Only the clock's owner can do this: acknowledge it, satisfy it, or choose at its date. | Hand the clock to its owner: next is where they act on it. |
| <a id="needs_grant" />`needs_grant` | 403 | `job.approve` | A grant this step needs isn't live: not given yet, expired or revoked. | Hand the party the grant link in next; the step runs once they grant it. |
| <a id="ineligible" />`ineligible` | 403 | 5 operations | The member can't take this Task: the answer names the first eligibility predicate they fail, and its cure. | Read predicate and cure. A credential, a region or coverage is cured at /join and by the verifier; availability by setting it on. |
| <a id="not_cleared" />`not_cleared` | 403 | 5 operations | The packet opens only to the member who claimed the Task and cleared it. | Claim the Task, then clear it: attest each statement on its sheet. |
| <a id="not_on_site" />`not_on_site` | 403 | `task.arrive`, `task.complete` | The check-in is outside the site radius, or outside the window's early and late marks. | Check in from the site, inside the window. The refusal names the distance and the time. |
| <a id="reserved" />`reserved` | 403 | `task.attest` | The rules reserve this act to a credential the person who attested doesn't hold. Nothing was charged. | A person who holds reserved_to attests it, in the region the rule names. The refusal names the act, who it is reserved to and the row it cites. |
| <a id="act_refused" />`act_refused` | 403 | `service.order` | The rules refuse this act here: it is never performed by this brand. Nothing was charged. | Follow cure.route: the act is performed there, never here. The refusal names the act and the row it cites. |
| <a id="talk_off" />`talk_off` | 403 | `job.message`, `job.thread`, `task.message` | This Service's jobs have no thread: its talk is off. | Reach the brand another way, or order a Service whose talk is on. |
| <a id="needs_the_party" />`needs_the_party` | 403 | 6 operations | Only the party can do this, through their own link. | Hand them the link in next. |

### `guard` codes

| Code | HTTP | Operations | Means | Fix |
|---|---|---|---|---|
| <a id="guard_refused" />`guard_refused` | 422 | `job.approve`, `task.attest` | A guard refused the output, and says why. | Fix that value; the step stays open. |

### `unavailable` codes

| Code | HTTP | Operations | Means | Fix |
|---|---|---|---|---|
| <a id="not_live" />`not_live` | 403 | `service.order`, `job.again` | This Service takes no orders yet. | Join the waitlist in next. |
| <a id="region_not_ratified" />`region_not_ratified` | 403 | `service.order` | The rules don't ratify this act in the job's region yet. Nothing was charged. | Join the waitlist in next, and you hear when the region is ratified. |
| <a id="brand_unverified" />`brand_unverified` | 403 | `service.order` | A credential the brand itself holds is unverified or stale, so the act it covers waits. Nothing was charged. | Join the waitlist in next, and you hear when the brand's verifier renews it. |

### `api_error` codes

| Code | HTTP | Operations | Means | Fix |
|---|---|---|---|---|
| <a id="api_error" />`api_error` | 500 | every operation | Something failed on our side. | Send the same call again with the same Idempotency-Key; quote the request_id if it fails twice. |

## The fields each code adds

Every refusal carries the one shape. These codes add fields of their own, typed on the code, so `e.code === 'ineligible'` narrows to its predicate and its cure. Each is typed on its code, then shown as a call answers it. A field marked `?` can be left out.

### `not_on_site` fields

A check-in or a check-out outside the site's radius, or outside the window's marks.

| Field | Type |
|---|---|
| `distance_m` | `number` |
| `within_m` | `number` |
| `window` | `{ from: string; to: string }` |

### `reserved` fields

A reserved act a person who doesn't hold its credential tried to perform.

| Field | Type |
|---|---|
| `act` | `string` |
| `reserved_to` | `string` |
| `rule` | `RuleRef` |

### `act_refused` fields

An act the rules refuse here, ordered by name or performed by a Service: where it is performed instead.

| Field | Type |
|---|---|
| `act` | `string` |
| `rule` | `RuleRef` |
| `cure` | `{ route: string \| null }` |

```txt
→ POST /matters {"service":"litigate","max_usd":500,"key":"sue-initech"}
```

```json title="captured/legal-refused.txt · 403 · magic values: none"
{
  "type": "BLOCKED",
  "category": "blocked",
  "code": "act_refused",
  "reason": "litigate is never performed here: Litigation is retained directly, never ordered here.",
  "param": "service",
  "act": "litigate",
  "rule": {
    "version": "2026-10",
    "at": "shared.litigate",
    "position": "Litigation is retained directly, never ordered here."
  },
  "cure": {
    "route": "https://referrals.example.test/litigation"
  },
  "next": {
    "do": "hand_to_person",
    "url": "https://referrals.example.test/litigation",
    "arguments": {},
    "tool": null,
    "http": "GET https://referrals.example.test/litigation"
  },
  "doc_url": "https://api.lawyer/docs/errors/act_refused",
  "request_id": "req_cXmV9f",
  "simulated": true
}
```

### `ineligible` fields

A member who can't take a Task: the first predicate they fail, what it needs, what they hold, the cure in words, and in `next` the call that cures it (none for conflict or separation, by design).

| Field | Type |
|---|---|
| `predicate` | `Predicate` |
| `needs` | `string` |
| `holds` | `string` |
| `cure` | `string` |

```txt
→ POST /reviews/tsk_7Hq2/claim {}   # as mbr_out_of_region
```

```json title="captured/people-refusals.txt · 403 · ineligible · magic values: member = mbr_out_of_region, member = mbr_lapsed_coverage, member = mbr_eligible"
{
  "type": "BLOCKED",
  "category": "blocked",
  "code": "ineligible",
  "reason": "attorney needs bar admission in US-CA, and mbr_out_of_region holds it in ZZ.",
  "predicate": "region",
  "needs": "bar admission in US-CA",
  "holds": "bar admission in ZZ",
  "cure": "Add US-CA to your regions at /join; the verifier checks the admission.",
  "next": {
    "do": "hand_to_person",
    "url": "http://localhost:8787/attorneys/join",
    "arguments": {},
    "tool": null,
    "http": "GET http://localhost:8787/attorneys/join"
  },
  "doc_url": "https://api.lawyer/docs/errors/ineligible",
  "request_id": "req_RsJa4q",
  "simulated": true
}
```

### `region_not_ratified` fields

A reserved act outside the regions its row is ratified in.

| Field | Type |
|---|---|
| `act` | `string` |
| `region` | `string \| null` |
| `regions` | `readonly string[]` |
| `rule` | `RuleRef` |

```txt
→ POST /matters {"service":"contract-review","contract":{"url":"data:text/plain,A%20lease.","name":"lease.pdf"},"client":{"name":"Ada Lovelace","email":"ada@example.com"},"client_region":"US-FL","max_usd":99,"key":"lease-fl"}
```

```json title="captured/legal-region.txt · 403 · magic values: none"
{
  "type": "BLOCKED",
  "category": "unavailable",
  "code": "region_not_ratified",
  "reason": "advise is ratified in US-CA, US-NY, US-TX under rules 2026-10, and this order's region is US-FL.",
  "param": "client_region",
  "act": "advise",
  "region": "US-FL",
  "regions": [
    "US-CA",
    "US-NY",
    "US-TX"
  ],
  "rule": {
    "version": "2026-10",
    "at": "services['contract-review'].advise",
    "position": "Advice on a contract is legal advice in the client's state."
  },
  "next": {
    "do": "waitlist",
    "service": "contract-review",
    "arguments": {
      "email": null
    },
    "tool": null,
    "http": "POST http://localhost:8787/contract-review/waitlist",
    "url": "http://localhost:8787/contract-review"
  },
  "doc_url": "https://api.lawyer/docs/errors/region_not_ratified",
  "request_id": "req_cXmV9f",
  "simulated": true
}
```

### `brand_unverified` fields

An act under a credential the brand holds while that credential is unverified or stale.

| Field | Type |
|---|---|
| `act` | `string` |
| `credentials` | `readonly string[]` |
| `rule` | `RuleRef` |

```txt
→ POST /jobs {"service":"extension","year":2025,"max_usd":25,"key":"stale","metadata":{"sandbox":{"brand":"stale"}}}
```

```json title="captured/brand-credential.txt · 403 · magic values: metadata.sandbox.brand = verified, metadata.sandbox.brand = stale"
{
  "type": "BLOCKED",
  "category": "unavailable",
  "code": "brand_unverified",
  "reason": "file is performed under the brand's efin, which isn't verified and fresh.",
  "act": "file",
  "credentials": [
    "efin"
  ],
  "rule": {
    "version": "2026-10",
    "at": "services['extension'].file",
    "position": "An extension is e-filed under the brand's own e-file number."
  },
  "next": {
    "do": "waitlist",
    "service": "extension",
    "arguments": {
      "email": null
    },
    "tool": null,
    "http": "POST http://localhost:8787/extension/waitlist",
    "url": "http://localhost:8787/extension"
  },
  "doc_url": "https://filings.example/docs/errors/brand_unverified",
  "request_id": "req_m8cwgn",
  "simulated": true
}
```

### `needs_the_party` fields

Only the party can do it: their own link, or their own signed-in session, in `next`.

| Field | Type |
|---|---|
| `party?` | `string` |

```txt
→ POST /asks/ask_7Hq2 {"items":{"terms":{"answer":"Lessee"}}}   # its key, without the link
```

```json title="captured/hand-to-person.txt · 403 · magic values: none"
{
  "type": "BLOCKED",
  "category": "blocked",
  "code": "needs_the_party",
  "reason": "glossary waits on the buyer to answer. Only they can, through their own link. Hand them the link in next.",
  "param": "ask_7Hq2",
  "party": "the buyer",
  "next": {
    "do": "hand_to_person",
    "url": "http://localhost:8787/a/ask_7Hq2?t=8FaWT5EoCj4h-uMyjlXp3_",
    "arguments": {
      "ask": "ask_7Hq2"
    },
    "party": "buyer",
    "to": "answer",
    "items": [
      {
        "id": "terms",
        "label": "Which terms stay in English?",
        "status": "open"
      }
    ],
    "expires_at": "2026-11-01T14:02:11.000Z",
    "tool": null,
    "http": "GET http://localhost:8787/a/ask_7Hq2?t=8FaWT5EoCj4h-uMyjlXp3_"
  },
  "doc_url": "http://localhost:8787/docs/errors/needs_the_party",
  "request_id": "req_U7Z8lS",
  "simulated": true
}
```

### `period_taken` fields

The subject's period is held: the subject, the period, the job that holds it, and the follow-on Services its end offers.

| Field | Type |
|---|---|
| `subject` | `string` |
| `period` | `string` |
| `job` | `string` |
| `follow` | `readonly string[]` |

```bash
curl -X POST http://localhost:8787/glossary -H 'content-type: application/json' -d '{"account":"acme","year":"2025","terms":["Premises"],"max_usd":19,"key":"glossary-2025-again"}'   # a second order for 2025
```

```json title="captured/period-tabs.txt · 409 · magic values: none"
{
  "code": "period_taken",
  "reason": "account acme has Glossary for 2025 already: job_7Hq2, accepted. A second one for 2025 is a follow-on from it: glossary-revision.",
  "param": "year",
  "subject": "sbj_7Hq2",
  "period": "2025",
  "job": "job_7Hq2",
  "follow": [
    "glossary-revision"
  ],
  "next": {
    "do": "again",
    "arguments": {
      "id": "job_7Hq2",
      "service": "glossary-revision"
    },
    "tool": "reorder_job",
    "http": "POST http://localhost:8787/jobs/job_7Hq2/again"
  }
}
```

### `rule` fields

A refusal the rules bring names its row in `rule`, a `RuleRef`, printed as `rules <version> · <row>`. [Objects](https://services.dev/docs/reference/objects.md#rule_ref) shows it inside a body.

| Field | Type |
|---|---|
| `version` | `string` |
| `at` | `string` |
| `position` | `string` |
| `cite?` | `readonly string[]` |

## A member’s and a client’s codes, as served

The rest of the codes a member’s session or a client’s link meets, each as a real run answered it: its frame is titled with its code, and its body is whole on "Show all".

```txt
→ GET /reviews/tsk_7Hq2/packet   # as mbr_eligible, before clearing it
```

```json title="captured/people-refusals.txt · 403 · not_cleared · magic values: member = mbr_out_of_region, member = mbr_lapsed_coverage, member = mbr_eligible"
{
  "type": "BLOCKED",
  "category": "blocked",
  "code": "not_cleared",
  "reason": "tsk_7Hq2's packet opens only to the signer who claimed and cleared it.",
  "param": "id",
  "next": null,
  "doc_url": "https://api.lawyer/docs/errors/not_cleared",
  "request_id": "req_kOO8Pm",
  "simulated": true
}
```

```txt
→ POST /reviews/tsk_7Hq2/claim {}   # as mbr_lapsed_coverage, once mbr_eligible holds it
```

```json title="captured/people-refusals.txt · 409 · task_taken · magic values: member = mbr_out_of_region, member = mbr_lapsed_coverage, member = mbr_eligible"
{
  "type": "BLOCKED",
  "category": "conflict",
  "code": "task_taken",
  "reason": "tsk_7Hq2 is claimed by another signer.",
  "next": null,
  "doc_url": "https://api.lawyer/docs/errors/task_taken",
  "request_id": "req_Vuv04G",
  "simulated": true
}
```

```txt
→ POST /reviews/tsk_7Hq2/decline {}   # as mbr_eligible: a decline with no memo
```

```json title="captured/people-refusals.txt · 422 · memo_required · magic values: member = mbr_out_of_region, member = mbr_lapsed_coverage, member = mbr_eligible"
{
  "type": "BLOCKED",
  "category": "invalid_request",
  "code": "memo_required",
  "reason": "A decline carries a reasoned memo, for the client alone.",
  "param": "memo",
  "next": null,
  "doc_url": "https://api.lawyer/docs/errors/memo_required",
  "request_id": "req_av55x6",
  "simulated": true
}
```

```txt
→ POST /reviews/tsk_7Hq2/send_back {}   # as mbr_eligible: a send-back with no defects
```

```json title="captured/people-refusals.txt · 422 · defects_required · magic values: member = mbr_out_of_region, member = mbr_lapsed_coverage, member = mbr_eligible"
{
  "type": "BLOCKED",
  "category": "invalid_request",
  "code": "defects_required",
  "reason": "A send-back names its defects, so advise's work can be redone against them.",
  "param": "defects",
  "next": null,
  "doc_url": "https://api.lawyer/docs/errors/defects_required",
  "request_id": "req_NEowhM",
  "simulated": true
}
```

```txt
→ POST /matters/job_7Hq2/cancel   # the buyer, once a member declined
```

```json title="captured/people-refusals.txt · 409 · needs_direction · magic values: member = mbr_out_of_region, member = mbr_lapsed_coverage, member = mbr_eligible"
{
  "type": "BLOCKED",
  "category": "conflict",
  "code": "needs_direction",
  "reason": "tsk_7Hq2 was declined, and only the client's direct ask moves job_7Hq2 on: to another signer, or to an outcome.",
  "next": {
    "do": "hand_to_person",
    "url": "http://localhost:8787/a/ask_7Hq3?t=rE5VINsEvPPB93bDQLooDc",
    "arguments": {
      "ask": "ask_7Hq3"
    },
    "party": {
      "name": "Ada Lovelace",
      "email": "ada@example.com"
    },
    "to": "direct",
    "expires_at": "2026-11-01T14:02:11.000Z",
    "tool": null,
    "http": "GET http://localhost:8787/a/ask_7Hq3?t=rE5VINsEvPPB93bDQLooDc"
  },
  "doc_url": "https://api.lawyer/docs/errors/needs_direction",
  "request_id": "req_J52rjT",
  "simulated": true
}
```

## check’s gates

A failing gate exits 1 and prints its code in `check --json`. All 31, each one's meaning, its fix and its failing file, are on [check’s gates](https://services.dev/docs/reference/check.md).

## The CLI’s own codes

Before any brand answers, `npx services.dev` can fail on its own. With `--json`, or `SERVICES_DEV_JSON=1`, each prints the same shape with one of these codes, its `doc_url` this page's anchor. The exit code is the code's, so an agent branches on it without reading the words.

| Code | Category | Exit | Means |
|---|---|---|---|
| <a id="usage" />`usage` | `invalid_request` | 2 | The command is missing something it needs. |
| <a id="unknown_command" />`unknown_command` | `invalid_request` | 2 | No command by that name. |
| <a id="not_running" />`not_running` | `api_error` | 10 | Nothing is running at that URL. |
| <a id="not_a_brand" />`not_a_brand` | `invalid_request` | 2 | This folder has no Services, or one fails to load. |

A refusal from a brand exits by its category: `invalid_request` 3, `authentication` 4, `blocked` 5, `unavailable` 7, `conflict` 6, `guard` 6, `rate_limited` 10, `api_error` 10. A failing `check` exits 1, and usage 2. [The CLI](https://services.dev/docs/reference/cli.md) lists every command.

---

- Up: [Your first paid job](https://services.dev/docs.md)
- Previous: [Events](https://services.dev/docs/reference/events.md)
- Next: [Definition errors](https://services.dev/docs/reference/definition-errors.md)
