# Troubleshooting

Symptom-first recovery for connection, scope, project-reach, protocol, grant/lease, and question errors — with what is safe to retry versus when a human must act.

Start from the symptom and preserve durable state. Server control blocks name the stable error code, current state, permitted next operations, retryability, and any human action. If no authoritative response arrived, treat the outcome as unknown and read status before replaying a mutation.

## Tools are missing or empty after setup
<a id="missing-tools"></a>

Classify startup before changing credentials:

1. **Not configured:** add `https://mcp.semel.ai/mcp` with the exact [Quickstart](https://docs.semel.ai/quickstart) command.
2. **Starting or provider transient:** retry once with bounded backoff; do not erase credentials on timeout, 429, network failure, or 5xx.
3. **Terminal OAuth:** for `invalid_grant`, a rejected/used refresh token, missing provider refresh token, or logged-out state, stop concurrent clients sharing it and perform one harness-native login.
4. **Server has tools, model session does not:** reload the session; reauthorization will not fix stale model context.
5. **Some tools exist, one is absent:** request only its missing scope/capability.
6. Require live `initialize`, Semel `serverInfo`, non-empty `tools/list`, and the needed tools in the current model session.

## Authentication & scope errors
<a id="auth-and-scope"></a>

- **`AUTHENTICATION_REQUIRED`** — complete one harness-native OAuth login, or have an owner rotate the named token through a secret reference.
- **`AUTHORIZATION_SCOPE_MISSING`** — request only the scope named by the live tool/control block, then reload the session. An unchanged retry cannot work.
- **`PROJECT_ACCESS_DENIED` / `CONTEXT_FORBIDDEN`** — use a reachable project/source or ask an owner to change the allowlist. Never probe for hidden project data.
- **`PROTOCOL_VERSION_UNSUPPORTED`** — run the inspected installer and start a new session. Never mutate under incompatible or security-revoked skill bytes.

## Validation, versions, and idempotency
<a id="validation-and-replay"></a>

- **`PAYLOAD_REJECTED` / `VALIDATION_FAILED`** — repair the field, size, content, evidence, or prerequisite named in the safe response; do not repeatedly send the same invalid payload.
- **`CONFLICTING_IDEMPOTENCY_REPLAY`** — the key belongs to different arguments. Read status/receipts, then use the original exact arguments or a fresh key for a genuinely new mutation.
- **`BRIEF_VERSION_CONFLICT`** — reread the full current brief, preserve all intended replacement sections, and ask the human to resolve the substantive conflict.
- **No response / `CONTROL_PLANE_UNREACHABLE`** — the client observed no authoritative result. Reconnect and read status before replaying with the same idempotency key.

## Error codes
<a id="error-codes"></a>

The full server error taxonomy. “Safe to retry” means an unchanged retry can succeed; “needs operator action” means a human must do something (approve, re-grant, re-mint) before it will.

### AUTHENTICATION_REQUIRED

The request carried no valid bearer credential.

Retryable: no. Operator action: not supported.

### AUTHORIZATION_SCOPE_MISSING

The authenticated principal is missing a required scope.

Retryable: no. Operator action: supported.

### PROJECT_ACCESS_DENIED

The authenticated principal has no grant to reach this project.

Retryable: no. Operator action: supported.

### PROTOCOL_VERSION_UNSUPPORTED

No compatible protocol major overlaps the caller-supported range.

Retryable: no. Operator action: not supported.

### GRANT_REQUIRED

No operator-issued execution grant exists for this session yet.

Retryable: no. Operator action: supported.

### GRANT_EXPIRED

The execution grant is revoked, expired, or already consumed.

Retryable: no. Operator action: supported.

### LEASE_EXPIRED

The current epoch lease expired; a recovery or new claim is required.

Retryable: no. Operator action: not supported.

### STALE_FENCE

This write came from a fence generation that is no longer current.

Retryable: no. Operator action: not supported.

### SEQUENCE_GAP

The submitted sequence number is not the expected next value.

Retryable: no. Operator action: not supported.

### CONFLICTING_IDEMPOTENCY_REPLAY

The idempotency key was already used with different arguments.

Retryable: no. Operator action: not supported.

### QUESTION_OPEN

A durable question is open and awaiting an accepted answer.

Retryable: yes. Operator action: not supported.

### QUESTION_DELIVERY_DEGRADED

A notification channel is degraded; the canonical inbox record is unaffected.

Retryable: yes. Operator action: not supported.

### QUESTION_RESPONSE_DEADLINE_EXCEEDED

The response deadline passed with no accepted answer; the question stays open.

Retryable: yes. Operator action: supported.

### BRIEF_VERSION_CONFLICT

The pinned brief base moved before finalization.

Retryable: no. Operator action: supported.

### RUN_ALREADY_TERMINAL

The run is already terminal; read review_status — there is nothing to cancel.

Retryable: no. Operator action: not supported.

### CANCELLED

This session was cancelled; no further mutation can complete it.

Retryable: no. Operator action: not supported.

### PAYLOAD_REJECTED

The payload violated a bound, forbidden field, or content rule.

Retryable: no. Operator action: not supported.

### VALIDATION_FAILED

The submitted result failed a repairable schema/evidence/prerequisite rule.

Retryable: no. Operator action: not supported.

### CONTEXT_FORBIDDEN

The caller's scope or project grant does not reach this context source.

Retryable: no. Operator action: supported.

### CONTEXT_UNAVAILABLE

The requested context source or citation could not be resolved.

Retryable: yes. Operator action: not supported.

## Invalid calls and exact recovery
<a id="failure-fixtures"></a>

These deterministic fixtures preserve the actual boundary distinction: authenticated domain failures are MCP `result.isError` responses with matching text and structured bodies, while a rejected credential stops at the HTTP 401 challenge before any tool runs. Example IDs and timestamps are inert fixtures.

### Missing scope
<a id="failure-missing-scope"></a>

Call local review origination without review:execute.

**Invalid request**

```json
{
  "toolName": "review_start",
  "arguments": {
    "briefId": "brf_fixture_checkout",
    "execution": "local",
    "idempotencyKey": "review-start-local-v1"
  }
}
```

**MCP JSON-RPC error result**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"error\":{\"kind\":\"forbidden\",\"message\":\"this action requires the review:execute scope\",\"details\":{\"reason\":\"AUTHORIZATION_SCOPE_MISSING\",\"missingScope\":\"review:execute\",\"repair\":\"request_additional_scope\"},\"retryable\":false,\"requestId\":\"req_fixture_scope\"}}"
      }
    ],
    "structuredContent": {
      "error": {
        "kind": "forbidden",
        "message": "this action requires the review:execute scope",
        "details": {
          "reason": "AUTHORIZATION_SCOPE_MISSING",
          "missingScope": "review:execute",
          "repair": "request_additional_scope"
        },
        "retryable": false,
        "requestId": "req_fixture_scope"
      }
    },
    "isError": true
  }
}
```

**Correction:** A human grants only review:execute through delegated consent or agent-token configuration; reload the session and repeat the same logical mutation.

### Malformed input or cross-field refinement
<a id="failure-malformed-refinement"></a>

Omit both identifiers required by review_execution_status.

**Invalid request**

```json
{
  "toolName": "review_execution_status",
  "arguments": {}
}
```

**MCP JSON-RPC error result**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"error\":{\"kind\":\"validation\",\"message\":\"invalid arguments for review_execution_status: reviewSessionId or executionId is required\",\"details\":{\"issues\":[{\"code\":\"custom\",\"message\":\"reviewSessionId or executionId is required\",\"path\":[]}]},\"retryable\":false,\"requestId\":\"req_fixture_validation\"}}"
      }
    ],
    "structuredContent": {
      "error": {
        "kind": "validation",
        "message": "invalid arguments for review_execution_status: reviewSessionId or executionId is required",
        "details": {
          "issues": [
            {
              "code": "custom",
              "message": "reviewSessionId or executionId is required",
              "path": []
            }
          ]
        },
        "retryable": false,
        "requestId": "req_fixture_validation"
      }
    },
    "isError": true
  }
}
```

**Correction:** Supply one authoritative identifier returned by the claim or session status.

**Corrective call: `review_execution_status`**

```json
{
  "executionId": "xex_fixture_engineering"
}
```

### Conflicting idempotency replay
<a id="failure-idempotency-conflict"></a>

Reuse a checkpoint idempotency key with changed receipt arguments.

**Invalid request**

```json
{
  "toolName": "review_execution_checkpoint_append",
  "arguments": {
    "executionId": "xex_fixture_engineering",
    "fenceGeneration": 3,
    "seq": 3,
    "milestoneName": "validation_result",
    "safeSummary": "Changed payload.",
    "idempotencyKey": "checkpoint-3-original"
  }
}
```

**MCP JSON-RPC error result**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"error\":{\"kind\":\"conflict\",\"message\":\"The idempotency key was already used with different arguments.\",\"details\":{\"state\":{\"sessionState\":\"running\",\"executionId\":\"xex_fixture_engineering\",\"epoch\":3,\"protocolVersion\":\"1.1\",\"bundleVersion\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"},\"allowedNextOperations\":[{\"operation\":\"review_execution_sync\",\"preconditions\":[\"Follow the current server control block.\"]}],\"completion\":{\"complete\":false,\"unmetRequirements\":[\"The execution has not reached a terminal accepted submit.\"],\"certificateState\":\"not_applicable\"},\"progress\":{\"checkpointHighWaterMark\":2,\"openQuestionCount\":0,\"leaseExpiresAt\":\"2026-09-07T18:15:00.000Z\",\"suggestedPollAt\":\"2026-09-07T18:05:00.000Z\"},\"operatorAction\":{\"required\":false},\"error\":{\"code\":\"CONFLICTING_IDEMPOTENCY_REPLAY\",\"retryable\":false,\"currentState\":\"running\",\"permittedNextOperations\":[\"review_execution_sync\"],\"safeText\":\"The idempotency key was already used with different arguments.\"}},\"retryable\":false,\"requestId\":\"req_fixture_idempotency\"}}"
      }
    ],
    "structuredContent": {
      "error": {
        "kind": "conflict",
        "message": "The idempotency key was already used with different arguments.",
        "details": {
          "state": {
            "sessionState": "running",
            "executionId": "xex_fixture_engineering",
            "epoch": 3,
            "protocolVersion": "1.1",
            "bundleVersion": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
          },
          "allowedNextOperations": [
            {
              "operation": "review_execution_sync",
              "preconditions": [
                "Follow the current server control block."
              ]
            }
          ],
          "completion": {
            "complete": false,
            "unmetRequirements": [
              "The execution has not reached a terminal accepted submit."
            ],
            "certificateState": "not_applicable"
          },
          "progress": {
            "checkpointHighWaterMark": 2,
            "openQuestionCount": 0,
            "leaseExpiresAt": "2026-09-07T18:15:00.000Z",
            "suggestedPollAt": "2026-09-07T18:05:00.000Z"
          },
          "operatorAction": {
            "required": false
          },
          "error": {
            "code": "CONFLICTING_IDEMPOTENCY_REPLAY",
            "retryable": false,
            "currentState": "running",
            "permittedNextOperations": [
              "review_execution_sync"
            ],
            "safeText": "The idempotency key was already used with different arguments."
          }
        },
        "retryable": false,
        "requestId": "req_fixture_idempotency"
      }
    },
    "isError": true
  }
}
```

**Correction:** Read status and receipts. Replay the original unchanged arguments with the original key, or use a fresh key only for a new logical checkpoint.

**Corrective call: `review_execution_status`**

```json
{
  "executionId": "xex_fixture_engineering"
}
```

### Brief version conflict
<a id="failure-brief-version-conflict"></a>

Replace a brief using a stale ifVersionNum.

**Invalid request**

```json
{
  "toolName": "brief_update",
  "arguments": {
    "briefId": "brf_fixture_checkout",
    "content": {},
    "ifVersionNum": 4,
    "idempotencyKey": "brief-update-v4"
  }
}
```

**MCP JSON-RPC error result**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"error\":{\"kind\":\"conflict\",\"message\":\"brief moved to a newer version since you loaded it — reload and retry\",\"details\":{\"reason\":\"BRIEF_VERSION_CONFLICT\",\"ifVersionNum\":4,\"currentVersionNum\":5},\"retryable\":false,\"requestId\":\"req_fixture_brief_version\"}}"
      }
    ],
    "structuredContent": {
      "error": {
        "kind": "conflict",
        "message": "brief moved to a newer version since you loaded it — reload and retry",
        "details": {
          "reason": "BRIEF_VERSION_CONFLICT",
          "ifVersionNum": 4,
          "currentVersionNum": 5
        },
        "retryable": false,
        "requestId": "req_fixture_brief_version"
      }
    },
    "isError": true
  }
}
```

**Correction:** Reread the full brief, preserve every untouched key, reconcile the human-visible conflict, and use a new mutation key for the changed replacement.

**Corrective call: `brief_get_full`**

```json
{
  "briefId": "brf_fixture_checkout"
}
```

### Stale execution fence
<a id="failure-stale-fence"></a>

Heartbeat with a fence generation superseded by a handoff or recovery claim.

**Invalid request**

```json
{
  "toolName": "review_execution_heartbeat",
  "arguments": {
    "executionId": "xex_fixture_engineering",
    "fenceGeneration": 2,
    "idempotencyKey": "heartbeat-stale-fence"
  }
}
```

**MCP JSON-RPC error result**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"error\":{\"kind\":\"conflict\",\"message\":\"This write came from fence generation 2; the current generation is 3.\",\"details\":{\"state\":{\"sessionState\":\"running\",\"executionId\":\"xex_fixture_engineering\",\"epoch\":3,\"protocolVersion\":\"1.1\",\"bundleVersion\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"},\"allowedNextOperations\":[{\"operation\":\"review_execution_status\",\"preconditions\":[\"Follow the current server control block.\"]}],\"completion\":{\"complete\":false,\"unmetRequirements\":[\"The execution has not reached a terminal accepted submit.\"],\"certificateState\":\"not_applicable\"},\"progress\":{\"checkpointHighWaterMark\":2,\"openQuestionCount\":0,\"leaseExpiresAt\":\"2026-09-07T18:15:00.000Z\",\"suggestedPollAt\":\"2026-09-07T18:05:00.000Z\"},\"operatorAction\":{\"required\":false},\"error\":{\"code\":\"STALE_FENCE\",\"retryable\":false,\"currentState\":\"running\",\"permittedNextOperations\":[\"review_execution_status\"],\"safeText\":\"This write came from fence generation 2; the current generation is 3.\"}},\"retryable\":false,\"requestId\":\"req_fixture_stale_fence\"}}"
      }
    ],
    "structuredContent": {
      "error": {
        "kind": "conflict",
        "message": "This write came from fence generation 2; the current generation is 3.",
        "details": {
          "state": {
            "sessionState": "running",
            "executionId": "xex_fixture_engineering",
            "epoch": 3,
            "protocolVersion": "1.1",
            "bundleVersion": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
          },
          "allowedNextOperations": [
            {
              "operation": "review_execution_status",
              "preconditions": [
                "Follow the current server control block."
              ]
            }
          ],
          "completion": {
            "complete": false,
            "unmetRequirements": [
              "The execution has not reached a terminal accepted submit."
            ],
            "certificateState": "not_applicable"
          },
          "progress": {
            "checkpointHighWaterMark": 2,
            "openQuestionCount": 0,
            "leaseExpiresAt": "2026-09-07T18:15:00.000Z",
            "suggestedPollAt": "2026-09-07T18:05:00.000Z"
          },
          "operatorAction": {
            "required": false
          },
          "error": {
            "code": "STALE_FENCE",
            "retryable": false,
            "currentState": "running",
            "permittedNextOperations": [
              "review_execution_status"
            ],
            "safeText": "This write came from fence generation 2; the current generation is 3."
          }
        },
        "retryable": false,
        "requestId": "req_fixture_stale_fence"
      }
    },
    "isError": true
  }
}
```

**Correction:** Discard the local fence and inspect the authoritative execution before any mutation.

**Corrective call: `review_execution_status`**

```json
{
  "executionId": "xex_fixture_engineering"
}
```

### Expired execution lease
<a id="failure-expired-lease"></a>

Heartbeat after the current epoch lease has expired.

**Invalid request**

```json
{
  "toolName": "review_execution_heartbeat",
  "arguments": {
    "executionId": "xex_fixture_engineering",
    "fenceGeneration": 3,
    "idempotencyKey": "heartbeat-expired-lease"
  }
}
```

**MCP JSON-RPC error result**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"error\":{\"kind\":\"conflict\",\"message\":\"The current epoch lease already expired; reclaim via review_execution_claim.\",\"details\":{\"state\":{\"sessionState\":\"running\",\"executionId\":\"xex_fixture_engineering\",\"epoch\":3,\"protocolVersion\":\"1.1\",\"bundleVersion\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"},\"allowedNextOperations\":[{\"operation\":\"review_execution_claim\",\"preconditions\":[\"Follow the current server control block.\"]}],\"completion\":{\"complete\":false,\"unmetRequirements\":[\"The execution has not reached a terminal accepted submit.\"],\"certificateState\":\"not_applicable\"},\"progress\":{\"checkpointHighWaterMark\":2,\"openQuestionCount\":0,\"leaseExpiresAt\":\"2026-09-07T17:55:00.000Z\",\"suggestedPollAt\":\"2026-09-07T18:05:00.000Z\"},\"operatorAction\":{\"required\":false},\"error\":{\"code\":\"LEASE_EXPIRED\",\"retryable\":false,\"currentState\":\"running\",\"permittedNextOperations\":[\"review_execution_claim\"],\"safeText\":\"The current epoch lease already expired; reclaim via review_execution_claim.\"}},\"retryable\":false,\"requestId\":\"req_fixture_expired_lease\"}}"
      }
    ],
    "structuredContent": {
      "error": {
        "kind": "conflict",
        "message": "The current epoch lease already expired; reclaim via review_execution_claim.",
        "details": {
          "state": {
            "sessionState": "running",
            "executionId": "xex_fixture_engineering",
            "epoch": 3,
            "protocolVersion": "1.1",
            "bundleVersion": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
          },
          "allowedNextOperations": [
            {
              "operation": "review_execution_claim",
              "preconditions": [
                "Follow the current server control block."
              ]
            }
          ],
          "completion": {
            "complete": false,
            "unmetRequirements": [
              "The execution has not reached a terminal accepted submit."
            ],
            "certificateState": "not_applicable"
          },
          "progress": {
            "checkpointHighWaterMark": 2,
            "openQuestionCount": 0,
            "leaseExpiresAt": "2026-09-07T17:55:00.000Z",
            "suggestedPollAt": "2026-09-07T18:05:00.000Z"
          },
          "operatorAction": {
            "required": false
          },
          "error": {
            "code": "LEASE_EXPIRED",
            "retryable": false,
            "currentState": "running",
            "permittedNextOperations": [
              "review_execution_claim"
            ],
            "safeText": "The current epoch lease already expired; reclaim via review_execution_claim."
          }
        },
        "retryable": false,
        "requestId": "req_fixture_expired_lease"
      }
    },
    "isError": true
  }
}
```

**Correction:** Read status, then follow only the returned recovery or fresh human-grant claim path.

**Corrective call: `review_execution_status`**

```json
{
  "executionId": "xex_fixture_engineering"
}
```

### Review configuration missing
<a id="failure-configless-review"></a>

Start the first review for a project with no configured AI reviewer.

**Invalid request**

```json
{
  "toolName": "review_start",
  "arguments": {
    "briefId": "brf_fixture_checkout",
    "idempotencyKey": "review-start-configless"
  }
}
```

**MCP JSON-RPC error result**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"error\":{\"kind\":\"validation\",\"message\":\"configure at least one AI reviewer in the portal before starting the first review pass\",\"retryable\":false,\"requestId\":\"req_fixture_configless\"}}"
      }
    ],
    "structuredContent": {
      "error": {
        "kind": "validation",
        "message": "configure at least one AI reviewer in the portal before starting the first review pass",
        "retryable": false,
        "requestId": "req_fixture_configless"
      }
    },
    "isError": true
  }
}
```

**Correction:** A human configures at least one project reviewer/provider/model in the Semel portal; then the agent retries review_start with a new logical-attempt key.

### Pinned artifact publication missing
<a id="failure-missing-artifact-publication"></a>

Fetch a pinned active skill whose exact role/version/hash row or bytes are unavailable.

**Invalid request**

```json
{
  "toolName": "review_execution_skill_get",
  "arguments": {
    "executionId": "xex_fixture_engineering",
    "role": "engineering"
  }
}
```

**MCP JSON-RPC error result**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"error\":{\"kind\":\"not_found\",\"message\":\"the pinned engineering skill artifact is unavailable for this execution\",\"details\":{\"state\":{\"sessionState\":\"running\",\"executionId\":\"xex_fixture_engineering\",\"epoch\":3,\"protocolVersion\":\"1.1\",\"bundleVersion\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"},\"allowedNextOperations\":[{\"operation\":\"review_execution_status\",\"preconditions\":[\"Follow the current server control block.\"]}],\"completion\":{\"complete\":false,\"unmetRequirements\":[\"The execution has not reached a terminal accepted submit.\"],\"certificateState\":\"not_applicable\"},\"progress\":{\"checkpointHighWaterMark\":2,\"openQuestionCount\":0,\"leaseExpiresAt\":\"2026-09-07T18:15:00.000Z\",\"suggestedPollAt\":\"2026-09-07T18:05:00.000Z\"},\"operatorAction\":{\"required\":false},\"error\":{\"code\":\"PAYLOAD_REJECTED\",\"retryable\":false,\"currentState\":\"running\",\"permittedNextOperations\":[\"review_execution_status\"],\"safeText\":\"the pinned engineering skill artifact is unavailable for this execution\"}},\"retryable\":false,\"requestId\":\"req_fixture_publication\"}}"
      }
    ],
    "structuredContent": {
      "error": {
        "kind": "not_found",
        "message": "the pinned engineering skill artifact is unavailable for this execution",
        "details": {
          "state": {
            "sessionState": "running",
            "executionId": "xex_fixture_engineering",
            "epoch": 3,
            "protocolVersion": "1.1",
            "bundleVersion": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
          },
          "allowedNextOperations": [
            {
              "operation": "review_execution_status",
              "preconditions": [
                "Follow the current server control block."
              ]
            }
          ],
          "completion": {
            "complete": false,
            "unmetRequirements": [
              "The execution has not reached a terminal accepted submit."
            ],
            "certificateState": "not_applicable"
          },
          "progress": {
            "checkpointHighWaterMark": 2,
            "openQuestionCount": 0,
            "leaseExpiresAt": "2026-09-07T18:15:00.000Z",
            "suggestedPollAt": "2026-09-07T18:05:00.000Z"
          },
          "operatorAction": {
            "required": false
          },
          "error": {
            "code": "PAYLOAD_REJECTED",
            "retryable": false,
            "currentState": "running",
            "permittedNextOperations": [
              "review_execution_status"
            ],
            "safeText": "the pinned engineering skill artifact is unavailable for this execution"
          }
        },
        "retryable": false,
        "requestId": "req_fixture_publication"
      }
    },
    "isError": true
  }
}
```

**Correction:** Stop execution and ask an operator to publish the exact pinned role/version/hash. Check status after publication; never substitute latest bytes.

**Corrective call: `review_execution_status`**

```json
{
  "executionId": "xex_fixture_engineering"
}
```

### Revoked or rejected login
<a id="failure-revoked-login"></a>

Initialize MCP with a bearer credential the server evaluated and rejected.

**Invalid request**

```json
{
  "method": "POST",
  "url": "https://mcp.semel.ai/mcp",
  "bearer": "<redacted rejected credential>"
}
```

**HTTP authentication challenge**

```json
{
  "status": 401,
  "headers": {
    "cache-control": "no-store",
    "www-authenticate": "Bearer resource_metadata=\"https://mcp.semel.ai/.well-known/oauth-protected-resource/mcp\", error=\"invalid_token\""
  }
}
```

**Correction:** Stop concurrent clients sharing the credential, complete one harness-native login, reload the session, and require live initialize plus tools/list before continuing.

## Grants, leases, and lost sessions
<a id="sessions"></a>

Call `review_execution_status`, then `review_execution_sync`, before recovery. **`GRANT_REQUIRED` / `GRANT_EXPIRED`:** create a grant request if permitted and wait for a human to approve a fresh grant. **`LEASE_EXPIRED` / `STALE_FENCE`:** stop mutating with the old claim and follow the returned legal claim path. **`SEQUENCE_GAP`:** synchronize and send exactly the next sequence; never skip or renumber history. **`RUN_ALREADY_TERMINAL` / `CANCELLED`:** read final status and stop. Do not create duplicate reviews, sessions, or epochs.

## Questions and notification delivery
<a id="questions-and-notifications"></a>

**`QUESTION_OPEN`** means execution is waiting for an accepted human answer; poll/read status without inventing one. **`QUESTION_DELIVERY_DEGRADED`** means Slack/email delivery is impaired while the canonical Semel inbox record remains valid; direct the human to Semel. **`QUESTION_RESPONSE_DEADLINE_EXCEEDED`** leaves the question open and may supply an operator URI; a person decides the response or recovery.

## Context and export failures
<a id="context-and-export"></a>

**`CONTEXT_UNAVAILABLE`** is retryable only as the returned control block permits; relist sources and search again rather than guessing a citation. If `brief_export_package` fails, no implementation-ready package exists. Repair the reported brief/export condition and retry with the correct idempotency behavior; do not fall back to deprecated `brief_export_markdown` as a verified handoff.

## Installer and update recovery
<a id="installer-recovery"></a>

Unknown release key, invalid Ed25519 signature, identity/hash mismatch, incompatible protocol, malformed skill metadata, or a non-HTTPS artifact URL must stop installation. Keep the prior copy. `failed_restored` means the old verified copy was restored; inspect the reason before retrying. `failed_restore` reports backup paths and needs manual operator restoration. A custom local file is refused unless the operator has preserved changes and deliberately chooses `--allow-custom`.

Canonical page: https://docs.semel.ai/troubleshooting
