# Status and error reference

> Every status word the product shows (connections, incidents, runs, changes, approvals, findings, licence) with its meaning and next step, and the HTTP error strings with their fixes.

_Reference · Updated 2026-10-27 · Describes release 0.1.164_

The vocabulary the product uses for state, one table per object, and the error strings a workspace member meets through the API or the portal. Each row says what the word means and what to do. The guides that explain the behaviour behind a state are linked from each section.

## Connection statuses {#connection-statuses}

A read connection is judged against its **current configuration revision**: a rotated secret or an edited config drops a verdict until the next test. The Quick start, the Connect page and the connection table all read the same server-side state.

| `verification_state` | Meaning | Next step |
|---|---|---|
| `not_configured` | No read-role connection exists yet. | Add one under **Data sources**. |
| `saved_unverified` | Saved, but never tested, tested on an older revision, or tested before revision tracking. The reason code says which (`never_tested`, `stale_revision`, `revision_untracked`). | **Verify connection** (one real read against the current credentials). |
| `verifying` | A probe is queued with the workspace's private-network agent and has not answered yet (`probe_queued`). | Wait; the control plane's own probe is synchronous and never shows this. |
| `verified` | The last test passed on the current revision (`ok`), or on a row untouched since before revision tracking (`ok_pre_revision_tracking` — re-test when convenient). | Nothing. |
| `needs_fix` | The last test failed, or passed from the control plane only (`reader_untrusted`). | Read the reason code below and the test detail. |
| `unverified_from_this_network` | The platform has no vantage point on the endpoint (`unreachable_from_platform`): a cluster-DNS, private-IP or single-label host — or a FortiGate or PAN-OS connection whose management address is private (`inside_network`). | Install the private-network agent, or expose a route; for `inside_network`, run **Harvest now** on the connection. |
| `needs_owner` | The state is not `verified` and the signed-in member lacks `datasources.manage`, so the fix is someone else's. | Ask a workspace owner or operator. |

Reason codes (`reason_code` on the state, `code` on the test response, `last_test_code` on the row):

| Code | Meaning | Fix |
|---|---|---|
| `ok` | The read succeeded. | — |
| `auth_failed` | The credential was rejected (`401`, `403`, `AccessDenied`, a bad signature). | Check the token or key fields; for a keyless AWS role, the role's trust policy. |
| `config_missing` | A required field is empty or still a `${…}` placeholder. | Fill the connection form. |
| `unreachable` | Connection refused or timed out, or the name did not resolve, from the control plane. | Check the URL and firewall, or use the private agent. |
| `blocked_by_guard` | The address is blocked by the platform's network guard (link-local, metadata, a private range with the guard on). | Add the host to `ssrf_allow_hosts` or turn the guard off for the workspace (Guardrails). |
| `unreachable_from_platform` | No vantage point: the platform did not attempt the read. | Private-network agent. |
| `inside_network` | A FortiGate or PAN-OS connection whose management address is private, with the network guard on: **Test** does not dial it from the platform (not a failure); the estate harvest reads it from inside your network. | **Harvest now** on the connection, then read its Coverage. |
| `probe_failed` | The test failed for a reason none of the above matched. | Read the detail on the test response. |
| `probe_queued` | Handed to the private-network agent. | Wait. |
| `reader_untrusted` | A keyless AWS role answered the control plane but its trust policy does not allow the workspace reader that scans and investigations run as. | Test again for the exact trust statement to add. |
| `never_tested`, `stale_revision`, `revision_untracked` | See `saved_unverified`. | Verify connection. |

`POST /api/aiops/{tenant_id}/datasources/{id}/test` answers `status` `ok`, `failed` or `unreachable_from_platform`, with `code`, `vantage` (`control_plane` or `private_agent:<name>`), `probe_queued`, `config_revision` and `execution_capability`. Grounding of a suggested connection, route or collection answers `ready`, `needs_credentials` (supply the listed `missing_secret_fields`), `needs_endpoint` (the URL is network-scoped — expose it or use the agent), `needs_datasource` (connect the `depends_on` type first) or `invalid` (it references something that does not exist). Apply refuses `invalid` and `needs_datasource` with `422`; the other verdicts only warn. The table's **Enabled** column reads `enabled`, `disabled` or `type disabled by platform`; the **Last test** column reads `ok`, `ok · from your private-network agent`, `ok from the control plane only`, `failed · <reason>`, `not tested from the platform`, `stale — verify again` or `never`. Setup and troubleshooting: [Manage connections](/help/manage-connections.md#troubleshooting).

## Alert statuses {#alert-statuses}

| Status | Meaning |
|---|---|
| `received` | Stored, not yet grouped. |
| `correlated` | Grouped into an incident as its first alert. |
| `suppressed` | Joined an incident whose grouping key it shares, or was named a downstream victim by the analysis; not individually triaged. |
| `ignored` | Cleared: the source resolved it, or a risk acceptance holds it down. |

Firing and clearing per source, the grouping key and grouping by the service graph are in the [Webhook reference](/help/webhook-reference.md#identity-grouping-and-storms).

## Incident statuses {#incident-statuses}

| Status | Meaning | How it moves on |
|---|---|---|
| `open` | Opened with no analysis running: held at intake (no service, no identity labels, a built-in warning rule) or the pillar is off. | **Analyse**, or the source clears every alert. |
| `investigating` | An analysis run is in flight or has finished with a proposal. | The run pauses for an approval, escalates, or a fix is applied. |
| `awaiting_approval` | A run is paused on a tool approval, or a release waits for its approver(s). | Someone with `approvals.decide` decides. |
| `remediating` | A fix was released; validation has not judged it yet. | A verify verdict, or a reopen. |
| `resolved` | Closed by a person, by every source alert clearing, by a verified fix, by a merge (grouping, a rule or a person) or a legacy storm split, as noise, or by a risk exception. | A new alert inside the reopen window reopens it, unless it was closed as noise; otherwise a new incident. |
| `escalated` | Handed to a person: the agent proposed no automated fix, a run failed, a budget tripped, a fix did not hold, or someone pulled **Escalate**. | **Mark resolved**, **Re-analyse**, or the quiet-expiry auto-close. |

Auto-close rules: the platform closes an incident from `open` or `investigating` the moment every source alert resolves, never from under a person at `awaiting_approval` or `remediating`; an `escalated` incident whose alerts all cleared and nothing re-fired for the quiet window (6 h by default) is closed with the note *auto-resolved: every source signal cleared and nothing re-fired for …*. Severity, priority and the risk tier are defined in [Incidents](/help/how-incidents-work.md#severity-priority-and-risk-tier).

### The summary state and its next step {#the-summary-state-and-its-next-step}

The incident page shows one derived state, one headline and one next action, computed by fixed precedence from the rows the detail endpoint returns — never a model call. Only `analysing` and `verifying` animate.

| State | Label shown | Meaning | Next action offered |
|---|---|---|---|
| `queued` | queued | No agent has picked the run up (*Queued — waiting for a runner*), or the runner's lease expired and the sweep has not resumed it. | — |
| `analysing` | analysing | The run is working through the evidence. | — |
| `approval_pending` | approval pending | The run is paused on a policy approval for a tool call (`records_approval`; `needs_second_approver` at L3). | **Decide the approval** (`approvals.decide`) |
| `quorum_partial` | needs a second approver | An L3 action or release has one of two approvals. | **Approve as the second approver** / **Open the change record** |
| `stale_gate` | stale approval gate | Marked awaiting approval but nothing is pending — the run died or the request was decided elsewhere. | **Stop this run, then re-analyse or resolve** |
| `fix_proposed` | review needed | The analysis is complete and proposes a fix; nobody applied it. *Investigation complete — no runnable fix* when no typed step can run. | **Apply fix** / **Review proposed change** / **Re-analyse** when a resource was suppressed after the plan |
| `fix_sent_pr` | PR merged | The fix went out as a pull request that was merged; validation pending. | **Verify now** |
| `waiting_for_merge` | waiting for merge | The pull request is open; nothing changes until a human merges it. | **Merge it in your repository** |
| `fix_applied_live` | fix applied | A live write ran through a route; validation pending. | **Verify now** |
| `verifying` | verifying | A read-only check is running. | — |
| `recovery_verified` | recovery verified | Validation found the condition cleared after the attempt. | **Mark resolved** |
| `fix_did_not_hold` | fix did not hold | Validation found the condition still present. | **Apply fix** (a newer proposal), **Re-analyse**, or **Escalate** |
| `execution_failed` | execution failed | The newest released fix failed before any validation verdict, and no analysis started after it; nothing may have been applied. | **Choose the next step** (opens L5: give feedback, mark resolved or as noise, re-analyse, roll back or hand off) |
| `run_failed` | run failed | The analysis did not finish (distinct from a tool failing inside a run). | **Re-analyse** |
| `handed_over` | Needs attention | Escalated, no plan, an unparseable wrap-up, a reopen after a failed validation, or an execution receipt still pending (*do not retry*). | **Mark resolved** or **Escalate** |
| `budget_blocked` | budget exhausted | The per-incident AI budget is spent. | **Continue analysis (+$5)** (`incidents.act`) |
| `closed_by_operator` | closed | A person closed it, or the post-fix check confirmed the fix. | — |
| `closed_by_source` | auto-resolved | The alert source cleared every grouped alert. | — |
| `closed_by_platform` | closed | Merged into another incident as a duplicate (grouped under the service it depends on, or merged by a person), or every flagged resource suppressed by a scan. | — |
| `closed_noise` | closed as noise | Closed as expected / no action required; verification muted. | — |
| `no_analysis` | no analysis | Nothing ran: held for triage (*Held for triage — <reason>*), a finding with no prepared fix, or the pillar is disabled. | **Analyse** when the hold allows it |

Every next action states what it does to the estate before the click: *opens a pull request*, *a live write via the matched route*, *records your approval*, *records one approval — a second, distinct approver releases it*, *the route's change window is closed*, *review the prepared change first*, or *a read-only check*. The actions and their permissions are described in [Actions](/help/approve-and-run-a-fix.md#actions).

## Investigation statuses {#investigation-statuses}

| Status | Meaning |
|---|---|
| `running` | Claimed by a runner (or the embedded engine) and in progress. A row with no runner claim yet shows as *queued* on the incident page. |
| `paused_approval` | Waiting on one or more tool approvals; resumes when they are decided. An approval left undecided past the platform TTL (24 h) fails the run. |
| `done` | Finished with a structured wrap-up. |
| `failed` | Ended without a conclusion: a model or gateway error, the step cap, a disabled pillar, a budget or licence block at start, or retries exhausted after a runner died. |
| `cancelled` | Stopped by **Stop this run** (`POST …/investigations/{id}/cancel`). |

Runs with trigger `chat`, `benchmark` and `api` are hidden from the investigation list and `404` on the detail endpoint. An estate x-ray scan carries its own status: `running`, `done`, `failed`, `aborted_budget` (the scan budget ran out; the report is still rendered from what was recorded) or `cancelled`.

## Approval decisions and risk tiers {#approval-decisions-and-risk-tiers}

A paused tool call or a change release carries one decision and one tier.

| Decision | Meaning |
|---|---|
| `pending` | Waiting. Shown on **Needs you** and `GET …/pending-approvals`. |
| `approved` | Released as proposed. |
| `denied` | Refused; the run continues without the action. |
| `edited` | Approved with a human-modified command (`edited_command` required). |

| Tier | Base channel | Who releases |
|---|---|---|
| `L0` | No matched write path: a suggestion a person applies by hand. | One approver (`approvals.decide`). |
| `L1` | A pull request (`gitops_pr`): the merge is the second pair of eyes. | One approver. |
| `L2` | A typed API, MCP or CLI write; any write on a production service (`env`, `environment`, `stage` or `tier` reading `prod`, `production`, `prd` or `live`). | One approver; a change window may gate the release. |
| `L3` | A network device push, or a blast radius of three or more services reached through declared or traced dependencies. | Two distinct approvers (`approvals.decide`); a change window gates the release. |

The derived tier is a floor: a route's own tier may raise it, never lower it. Paused tool calls need `approvals.decide`. For prepared fixes only, an operator with `incidents.act` may release a non-emergency standard change made standard by a matched runbook at a one-approver tier — a certified runbook route's at any priority, P1 included; normal, emergency and L3 release rules are unchanged. A release outside the route's change window is `403` until the window opens (an emergency change gives way once both L3 approvals are in). Policy detail: [The approval gate](/help/approve-and-run-a-fix.md#the-approval-gate).

## Change statuses and outcomes {#change-statuses-and-outcomes}

A change record is minted before any write (the Change hub); its status is the lifecycle of that one write.

| Status | Meaning |
|---|---|
| `draft` | Opened without a plan yet. |
| `planned` | The analysis's proposed fix, minted at wrap-up as a change request (class `standard`, `normal` or `emergency`). Hidden from the changes list unless asked for. |
| `pending_approval` | Requested; waiting for the approvals its tier needs. |
| `approved` | Every approval in; not yet dispatched. |
| `dispatching` | Durably reserved; the execution receipt is pending — never retry while it shows. |
| `executing` | The write ran (a pull request opened or a live write landed); validation pending. |
| `verifying` | A verification is running on it. |
| `completed` | Verified: the fix held. |
| `failed` | The execution failed, or validation found the condition still present. The rollback sweep decides what happens next. Also a change whose verification stopped without a verdict (it ran out, or a person used **Close without verdict**): the verdict reads `uncertain` and nothing rolls back on it until a later verdict decides. |
| `not_needed` | The run stopped because its only target already complied, before any write (a backup it took stays): nothing was changed. No rollback is offered and the rollback sweep skips it; audit `change.not_needed` carries the reason. |
| `rolling_back` | A rollback was dispatched and awaits its receipt. |
| `rolled_back` | The rollback landed (a restore pull request merged, or a compiled inverse applied). |
| `rejected` | A person rejected the request, or its pull request was closed unmerged. |
| `recorded` | An ingested external change (a push, a merge, a harvested cloud write, a ticketed change): an observation, never an executable request. `authorized: false` marks one that fell in a freeze window or used the platform's credential without a platform receipt (an unauthorized change), or that the source denied (unauthorized access — a denied attempt, never counted as an unauthorized change). |

Per attempt, the incident's **Remediation history** derives one **outcome**:

| Outcome | Rule |
|---|---|
| `validated` | A verify after the attempt returned `cleared`. |
| `did not hold` | The newest verify after the attempt returned `still_present`. |
| `superseded by a later fix` | Another attempt followed before any verdict. |
| `not validated yet` | No verdict so far. |

Verify verdicts on an incident (`IncidentRecheck.verdict`): `cleared`, `still_present`, `uncertain` (the check could not decide — `UNCERTAIN — cannot verify:` leads a coverage gap), and `running`, `skipped`, `failed` (no verify ran). The human **Verify now** bypasses the cost ladder.

Rollback decisions the daily sweep records for a `failed` change (audit actions):

| Action | When |
|---|---|
| `change.auto_rollback` | A verify-failed GitOps change at tier ≤ L2 opened its restore pull request on its own; or a failed post-change validation ran the compiled cloud inverse under `aiops_auto_rollback_cloud`; or an operator script ran under `aiops_auto_rollback`. |
| `change.rollback_skipped` | Nothing went live: the execution failed before a pull request was created, or the provider refused the request before acting; or no failed verification is on record. |
| `change.rollback_escalated` | A person must decide: the verification never concluded (`uncertain`), the tier is L3 (two-person release on the Changes page), the rollback is an agent draft, an operator-reported execution, or an unknown execution outcome that must be reconciled first. Sends the `rollback` notification event. |
| `change.rollback`, `change.rollback_merged`, `change.rollback_verified`, `change.rollback_cancelled` | A human-released rollback and its receipt, merge, verification or cancellation. |

Change windows, emergency changes and the ledger are explained in [Change windows, emergency changes and rollback](/help/change-control.md); execution review in [Review execution in Changes](/help/review-execution-in-changes.md#review-execution-in-changes).

## Finding and risk statuses {#finding-and-risk-statuses}

| Object | Values | Meaning |
|---|---|---|
| Cloud finding (Security Hub / Defender) | `open`, `cleared` | `cleared` when the scanner reports the finding resolved or passed; the register keeps the row with `cleared_at`. |
| Risk decision | `requested`, `approved`, `rejected` | A request by `incidents.act` or `approvals.decide`; approved or rejected by `approvals.decide` (self-approval only when no other approver exists, audited). Readers see approved rows only. |
| Risk decision outcome | `accept`, `avoid`, `mitigate` | The portal says **Suppress** for `accept` and **Fix** for `avoid`; it no longer offers `mitigate`, which older decisions keep. Accept resolves and suppresses re-sends until `expires_at` (90 days by default); avoid and mitigate open a change (180 days for mitigate). A superseding decision sets `revoked_at` on the old one. |
| Risk decision filter (`GET …/risk-decisions?state=`) | `requested`, `active`, `expired`, `revoked`, `rejected` | Any other value is `400 state must be requested\|active\|expired\|revoked\|rejected`. |
| Compliance control result | `pass`, `fail`, `unknown`, `not_applicable`, `accepted` | Per control per scan; `fail` opens or keeps a `control:<id>` compliance incident, a later `pass` closes it. |
| Attestation | `attested`, `not_applicable` | The manual layer on a framework requirement; a mandatory note, superseded rather than edited. |
| Scan | `running`, `done`, `failed` | A compliance scan. |

[Security posture](/help/security-posture.md) explains findings, decisions and frameworks.

## Licence states {#licence-states}

The platform verifies its licence at boot and on every scheduler tick and publishes the verdict for every component.

| State | Meaning | Effect |
|---|---|---|
| `unlicensed` | No public key is configured on the platform, so nothing is verified (development and test installs). | None — the licence is not enforced. |
| `valid` | Signature and claims check out and `exp` is in the future. | None. |
| `grace` | Expired less than the grace period ago (30 days unless the licence sets its own `grace_days`). | Runs continue; the reason reads *licence expired <date>; N day(s) of grace left*. |
| `expired` | Past the grace period. | New runs and approved releases are blocked: `409 platform licence is expired (…) — alerts and incidents keep recording; install a current licence to resume`; releasing a change answers `licence_blocked`. |
| `invalid` | The file does not verify (bad signature, wrong issuer or audience, a missing claim). | Blocked as for `expired`. |

Installing the licence is platform-administrator work; a workspace sees only the refusal.

## Run refusals {#run-refusals}

A run that must not start is refused with `409` and one of these reasons (also the `overall_reason` of the Quick start: `kill_switch`, `tenant_day`, `tenant_month`, `budget_exceeded`, `agents_paused`, `agent_offline`):

| Reason | Fix |
|---|---|
| `agents are paused for this tenant (kill switch) — alerts and incidents keep recording; re-enable on the Guardrails page` | **Resume all agents** on **AI budgets & kill switch**. |
| `daily cost budget exceeded ($x >= $y) — spend resumes at UTC midnight or raise the limit on the Guardrails page` | Raise or clear **Daily limit**. |
| `monthly cost budget exceeded ($x >= $y) — spend resumes on the 1st (UTC) or raise the limit on the Guardrails page` | Raise or clear **Monthly limit**. |
| `incident AI budget exceeded ($x >= $y) — a human decides: grant more budget on the incident page to continue, or take it by hand` | **Continue analysis (+$5)**. `409 per-incident budgets are not enabled for this tenant (Guardrails page)` when there is no per-incident limit to grant against. |
| `platform licence is <state> (…) — alerts and incidents keep recording; install a current licence to resume` | Platform administrator. |

Blocked alert-driven runs are never dropped: the incident is recorded, fails its run and escalates to a person.

## HTTP errors {#http-errors}

How to read a refusal: `401` is not signed in or a bad token; `403` names the missing permission; `404` is "not found" **or** "not a member of this workspace" (a non-member never learns that a workspace exists); `409` is a state conflict — the record moved, or the request contradicts a setting; `400` and `422` are input the server refuses, the body saying why; `429` is rate-limited. Cross-origin browser mutations from an unlisted origin are `403 cross-origin not allowed`.

### Pre-approval conflicts {#pre-approval-conflicts}

`POST /api/aiops/{tenant_id}/incidents/{incident_id}/preapprove` returns `409` with the reason the exact fix cannot become a runbook. The stable messages are:

- `No typed operation ran on this incident: only a fix the platform ran as typed steps can be pre-approved.`
- `The fix had manual steps beside its typed steps: only a fix made of typed steps alone can be pre-approved.`
- `A fix with multiple typed operations cannot be pre-approved as one runbook route; pre-approve each single-operation fix separately.`
- `The fix has not validated: pre-approve it once the post-fix check has passed.`
- `<operation> cannot be pre-approved: only an API or CLI fix, and never an operation that only undoes a fix.`
- `The alert that opened this incident has no alertname or service label for the next occurrence to match.`
- `The runbook route name already belongs to a different validated fix: refusing to overwrite its selector, operation or write connection. Certify a distinct route instead.`

A validated fix from a prior reopened occurrence is also refused until the current occurrence has its own successful typed execution and cleared validation. A person's recorded verification of a platform-executed typed fix is accepted; a manually applied fix is not a typed execution. A `403` means the caller lacks `incidents.act` or `approvals.decide`; route certification still uses `approvals.decide`.

### Authentication and permissions {#authentication-and-permissions}

| Status · `detail` | Cause | Fix |
|---|---|---|
| `401 not authenticated` | No session and no valid bearer token (expired, revoked, or the user is disabled). | Sign in, or create a new personal access token. |
| `403 requires permission '<perm>' on this tenant` | Your role lacks the permission the endpoint needs. | Ask an owner; the permission matrix is in [People, access and audit](/help/access-and-audit.md). |
| `403 token scope 'read' cannot <METHOD> <path> — needs 'write'` / `… cannot reach <path> — needs 'admin'` / `… cannot reach superadmin routes` | The token's scope ceiling is below the verb or route. | Mint a token with the `write` or `admin` scope. |
| `403 a '<scope>' token cannot mint a '<scope>' token` | A token may only mint tokens at or below its own scope. | Use the UI or a higher-scoped token. |
| `400 expires_days must be between 1 and 365` / `400 name required` | PAT lifetime or name. | Default lifetime is 90 days. |
| `403 superadmin required` | A platform-staff route. | — |
| `404 tenant not found` | The workspace id is wrong, or you are not a member. | Check `GET /api/aiops/me`. |
| `409 account pending activation in another workspace` / `409 this account was activated from another organization's invite link …` / an SSO refusal | The invited account belongs to another identity provider, is still pending, or was activated from another organization's invite link. | Members: invite-link and SSO rules in [People, access and audit](/help/access-and-audit.md). |

### Workspace settings, members and tokens {#workspace-settings-members-and-tokens}

| Status · `detail` | Cause | Fix |
|---|---|---|
| `400 settings key(s) managed via dedicated endpoints: …` | A protected key in `PATCH /api/aiops/{tenant_id}`. | Use the endpoint named in the [Settings reference](/help/settings-reference.md#how-settings-are-layered). |
| `400 <key> must be true, false or null` | A JSON switch sent as a string. | Send a JSON boolean. |
| `400 <key> must be a whole number from 0 to <cap>` / `… of 0 or more` | `aiops_storm_group_window_s`, `aiops_storm_spread_window_s`, `aiops_grouping_wait_s`, `aiops_reopen_window_h`, `aiops_flap_threshold`, `aiops_inventory_interval_s`. | Whole numbers only. |
| `400 aiops_auto_rollback_cloud must be "L1", "L2" or null` | | |
| `400 pii_patterns must be a list of at most 20 patterns` / `400 invalid pii pattern: …` / `400 invalid regex '…': …` | | |
| `400 max_cost_usd must be a number` / `400 max_cost_usd must be >= 0 (0 = uncapped)` | | |
| `400 <daily|monthly|incident>_cost_limit_usd must be >= 0 (0 = off)` | | |
| `400 scanner_sync_interval_s must be 0 (off), a whole number of seconds from 300 to 86400, or null (the platform default)` | | |
| `400 source_service_labels <reason>` | Bad shape for the source mappings the **Unidentified service — map this source** card saves. | `{source: [label, …]}`, ≤ 50 sources, ≤ 10 labels each. |
| `400 service_alias <reason>` | Bad shape for the **Service aliases** card, or a chain (a name that is both an alert service and an alias). | `{alert service: dependency-map service}`, ≤ 200 aliases, names 1–200 chars, no value also a key. |
| `400 unknown operation: …; expected one of …` | **Pre-approved operations** names an operation outside the vocabulary. | Pick from `known_operations`. |
| `400 model_route_policy …` | More than 10 deny prefixes, whitespace in a prefix, a label over 60 characters, or not an object. | |
| `400 auto_resolve.quiet_hours must be 1..168` / `… must be an integer` | | |
| `400 invalid golden_check cron '…'` / `400 golden_check.dataset_id must be one of …` / `400 golden_check.min_pass must be in (0, 100]` | | |
| `400 unknown notification kind '…'` / `400 notification needs at least one event` / `400 notification url must be https://` / `400 invalid email address '…'` / `400 a <pagerduty|opsgenie> target needs its <key>` / `400 <kind> region must be us or eu` / `400 a <kind> target pages on open, escalate and resolve only, not …` | **Incident notifications**. | |
| `400 oncall.rotation needs at least one email` / `400 oncall.period must be daily or weekly` / `400 override 'from' must precede 'to'` | **On-call schedule**. | |
| `400 smtp.host is required` / `400 smtp.port must be 1..65535` / `400 smtp.from must be an email address` | **Email delivery**. | |
| `409 auto_remediation cannot be armed in computer-assist mode — platform writes are disabled. Switch execution_mode to 'standard' first.` (and the same for `auto_remediation_direct`) | | |
| `422` on `retention_days`, `notify_min_interval_s`, `reopen_window_h`, `flap_threshold`, `change_class_policy` or a strict boolean | Out of range, or not the JSON type the field requires. | |
| `400 nothing to change` | An empty `PATCH /guardrails`. | |
| `422 schedule_cron '…' is not a valid cron expression` / `422 schedule_cron '…' never fires` | Pillar schedule. | Blank = event-driven. |
| `404 pillar agent not found` | | |
| `404 no user with email '…'` / `400 invalid email` / `400 email domain is reserved for platform staff` / `400 email address is reserved for platform staff` | Inviting a member. | |
| `404 no role named '…' in this tenant` / `409 '…' is a reserved builtin role name` / `409 role '…' already exists` / `400 builtin roles are not editable` / `400 builtin roles are not deletable` / `400 members still hold this role — reassign them first` | Roles. | |
| `400 support grants are revoked, not re-roled` / `409 account is not a pending invite or a local account of this workspace alone` | Members. | |
| `422 '<name>' is a reserved agent-token name` / `404 agent token not found` | Private-network agent tokens. | |

### Connections and routes {#connections-and-routes}

| Status · `detail` | Cause | Fix |
|---|---|---|
| `404 datasource type not found` / `404 datasource not found` | | |
| `409 datasource '<name>' already exists` | Names are unique per workspace. | |
| `400 Declare a write-capable connection before allowing approved execution.` | A route or connection asked for approved execution with no write-capable connection. | Add a `write` or `read_write` connection first. |
| `422 An Azure connection used for approved changes needs a Subscription ID: approved-plan execution is scoped to that subscription (an investigate-only connection may leave it blank).` | | |
| `409 Change CHG-… still needs this connection.` / `409 Remediation route '…' still uses this connection.` / `409 Discovery is still using this connection.` / `409 A Test Factory job is still using this connection.` / `409 A private-agent connection check is still running.` / `409 This connection was just added to another job or route.` | Deleting a connection something depends on. | Finish or detach the dependant first. |
| `409 Connection changed during the test; test the current credentials again.` | The config was edited while a probe ran. | Test again. |
| `409 This connection, or its connector type, is disabled.` | | |
| `422 Ticket systems are Jira, ServiceNow and Azure DevOps connections.` | **Use for tickets** on another type. | |
| `400 could not fetch the spec at <url>: …` / `400 the spec at <url> did not return a JSON object` / `400 paths is required` / `400 not pending for this datasource: …` | OpenAPI self-discovery on a generic API connector. | |
| `422 params.operations must be a list of at most 50 known operations: …` | A route's declared operations. | |
| `422 Redaction placeholders cannot be saved as route values. …` / `422 The route carries a value the platform would hide from its reviewers (…): a credential field repeats it. …` | A route payload carrying `[REDACTED…]` or a credential value. | Keep credentials in the connection. |
| `422 Choose an enabled write-capable connection supporting this action and explicitly allow approved execution.` / `422 The selected execution method does not support this guided action.` / `422 Confirm which repository owns this target's desired configuration.` | Route guidance. | |
| `422 A ticket route must use a connection of its own ticket system (Jira, ServiceNow or Azure DevOps).` / `422 A ticket route runs in api mode.` / `422 Run Check first — the route is missing …` / `422 pillars must list incident pillars (e.g. ["incident"]).` | Ticket routes. | |
| `422 A ticket system route is fixed bookkeeping and needs no certification.` / `422 Say why this route is safe to run without a per-incident click.` | Certifying a route. | |
| `422 Only a ticket system route can send a test ticket.` / `409 This ticket route is disabled, so no incident is ticketed …` / `409 The route's connection is missing or disabled.` | Test ticket. | |

### Incidents, approvals and changes {#incidents-approvals-and-changes}

| Status · `detail` | Cause | Fix |
|---|---|---|
| `404 incident not found` / `404 investigation not found` / `404 change not found` / `404 approval not found on this incident` / `404 artifact not found` | Wrong id, or not a member. | |
| `409 incident already resolved` / `409 cannot resolve an incident that is <status>` | Resolve from a state that does not allow it. | |
| `409 An approved action is in flight or its outcome is unknown. Reconcile that release before closing this incident.` | | Reconcile the dispatch first. |
| `409 an analysis of this incident is already in flight` | **Analyse** / **Re-analyse** while a run is running. | Wait or stop the run. |
| `409 validation is muted on this incident` | **Verify now** on a muted incident. | |
| `422 risk_accepted is set by a suppression on the control, not by a resolve` | | Use the finding's decision. |
| `409 Only an unmapped incident maps its source here.` / `400 The label '…' names a place or a field, not the service.` / `400 No alert of this incident carries a value for '…'.` / `409 Cannot map another label: …` | The **Unidentified service — map this source** card. | |
| `409 Nothing to retry: the ticket state is <state>.` / `409 The last attempt may have created the ticket. Retry in N s, once the ticket system's search has caught up.` / `409 No ticket route is enabled.` | Ticket retry. | |
| `400 amount_usd must be in (0, 1000]` / `409 per-incident budgets are not enabled for this tenant (Guardrails page)` | Budget grant. | |
| `400 decision must be approved, denied or edited` / `400 decision 'edited' requires edited_command` / `400 A redacted command cannot be executed. Supply a complete new command with an approved credential reference.` / `404 approval '…' not found` / `409 approval already decided: <decision>` | Deciding tool approvals (the first decision wins). | |
| `409 investigation is <status> — nothing to cancel` | | |
| `403 Remediation requires incidents.act or approvals.decide.` / `403 Action review requires incidents.act or approvals.decide.` / `403 Applying a change requires incidents.act or approvals.decide.` | | |
| `403 tier L3 requires 'approvals.decide'` | Releasing above your permission. | |
| `409 A route fix records no approval request: an approver releases it from this incident.` | A request-only call on a route fix. | |
| `409 Review the current action before approving it.` / `409 Review the exact action before applying it.` / `409 The exact action changed. Preview and review it again.` | The preview is stale or missing. | Open the review, then approve or apply. |
| `409 Select an approved action route and review its exact payload first.` / `409 Ingested changes are observations, not executable requests.` / `409 The incident behind this change is gone.` | | |
| `409 change is <status> — planning is over` / `409 change is <status> — nothing to verify yet` / `409 A post-change validation window is open until …` | | |
| `400 verdict must be cleared\|still_present\|uncertain` | Recording a manual verdict. | |
| `409 This change carries no class.` / `409 This change records a route run; its class cannot be changed.` / `409 This change has been dispatched; its class can no longer change.` / `409 already <class>` | Reclassifying. | |
| `409 A person may only raise a change class (normal → emergency); <from> → <to> would lower it. …` / `409 Standard because the certified runbook <name> covers this fix. To make it normal, demote or disable that runbook; …` | Reclassifying down, or a certified runbook's standard change. | Raise only; demote or disable the runbook to make its request normal. |
| `422 Confirm that the operation has stopped before reconciling it.` / `422 Confirm the action has stopped and identify exactly one release.` / `409 This change has no unresolved dispatch.` / `409 This change has no unresolved rollback.` / `409 Reconcile this forward action on its incident.` / `409 The runner still holds this job. Stop the action and wait for its lease to end before reconciling.` / `409 This approval has no unresolved release.` | Reconciling an uncertain execution. | |
| `409 This change has no current GitOps merge to confirm.` / `409 Rollback is in progress; reconcile it before reporting forward application.` / `409 Merge identity changed or is unavailable; refresh the change.` / `409 Change state moved while recording application; refresh and retry.` | Confirming a merge. | |
| `409 No typed rollback with a pending restoration read.` / `409 The original read connection is unavailable.` | Rollback. | |
| `409 a harvest is already running for this workspace` / `409 a findings sync is already running for this workspace` / `409 a scan is already running (<id>)` | One at a time. | |
| `400 ids must be a non-empty list` / `400 at most 500 incidents per call` | Bulk close. | |
| `400 summary is required` | Raising a concern. | |
| `404 no RCA to export` | | |

### Findings, compliance and the rest {#findings-compliance-and-the-rest}

| Status · `detail` | Cause | Fix |
|---|---|---|
| `403 requires permission 'incidents.act' or …` | Requesting a risk decision. | |
| `409 this is a suppression on a compliance control — decide on the control` | | |
| `404 riskdecision not found` | | |
| `422 bad date: …` / `422 to_date is before from_date` / `422 period longer than a year` / `422 to_date is in the future (reporting timezone: UTC)` | Posture trend ranges. | |
| `404 control not found` / `400 a reason is required to disable or N/A a control` / `404 unknown requirement ref` / `400 status must be attested\|not_applicable` / `400 a note is required — say what evidences this` | Controls and attestations. | |
| `422 <control> has no per-resource evidence — …` / `422 expires_at must be in the future` / `422 expires_at is at most N days out` / `409 another acceptance for this resource landed at the same …` | Suppressing a resource from a control. | |
| `404 lakehouse not enabled` / `404 x-ray not enabled` | The enterprise feature is not granted or its terms are not accepted. | Platform grant plus owner acceptance. |
| `400 kind must be one of …` / `400 interval_s must be 60..86400` / `400 lookback_s must be 60..604800` / `409 collection spec '…' already exists` / `400 query failed: …` / `400 match must be at least 3 characters` | Lakehouse. | |
| `413 file exceeds 5 MB` / `413 attachment exceeds 5 MB` / `415 file has binary content — text files only` / `400 could not extract PDF text: …` / `413 PDF too expensive to extract` / `429 another document is being extracted — retry shortly` | Estate x-ray attachments and file uploads into text fields. A PDF gets 20 seconds and a fixed memory budget for extraction; the pages finished when either runs out are kept, `413` means not even the first page finished in time, and `400 could not extract PDF text: MemoryError` means the first page alone exceeded the memory budget. Each workspace extracts one document at a time, so a second upload from the same workspace gets the `429` while the first runs. The other `413` the platform answers is the webhook body cap. | Retry once the first upload finishes; split or re-export a PDF that keeps hitting `413`. |
| `400 message required` / `409 a turn is already running for this session` / `409 a conversation's source cannot be changed; start a new conversation` / `422 provide a valid context_kind and context_id together` | Insights chat. | |
| `400 provide a rating, a score (1-10) …` / `400 score must be between 1 and 10` / `409 concurrent feedback update — retry` | Feedback. | |
| `409 expected events do not create recovery runbooks` / `409 a completed investigation with a recorded analysis is required` | Drafting a skill proposal. | |
| `404 dataset not found` / `404 dataset is in the trash — restore it first` / `409 dataset is not in the trash` / `400 format must be csv or json` / `400 dataset has no cases` / `404 benchmark run not found` / `409 run is <status> — nothing to resume` / `409 run is <status> — nothing to certify yet` | Test Lab. | |
| `409 only a proposed problem can be confirmed` / `409 problem already closed` | Problems. | |
| `400 Use one dependency per line: service -> dependency` / `400 No dependencies supplied` | The dependency editor. | |
| `404 unknown pillar` / `422 messages must contain user content` | The OpenAI-compatible agent API. | |
| `422 nothing to update` / `422 unknown rule id(s) …` / `422 turn built-in detection on before arming it` / `422 Keep shadow is on: untick Keep shadow first, …` | Built-in detection. | |
| `400 fmt must be json or csv` / `400 since must be before until` / `409 <replay busy>` | Audit export and verify. | |
| `404 validation not found` / `422 no sample for '<source>' yet — …` | Test alerts. | |

Webhook errors (`401 invalid webhook credentials`, `404 unknown webhook source …`, `413` over the body cap, `429` with `Retry-After`) are in the [Webhook reference](/help/webhook-reference.md#errors).


## Next steps

- Next: [Approval policy and change tiers](/help/approval-policy.md)
- [All Reference pages](/help/reference/llms.txt)
- [Documentation home](/help/)
