Skip to main content
Use the status code and machine-readable response fields to decide what to do next. Do not branch on a human-readable error sentence or assume that a timed out write failed.
Preview. The published OpenAPI operation remains the authority for its response codes and any endpoint-specific retry behavior.

Read response body

Most Registry, Skill, Agent, File, and MCP failures use an application/problem+json body with title, status, detail, and stable code. A refused request (400, 409, or 422) says why it was refused in detail when that cause is safe to publish; otherwise detail stays a generic sentence. Preserve trace_id when it is present. OTLP ingestion instead returns its documented JSON error shape with code, message, and details. Log the status, stable code, operation, and trace ID when available. Do not log the bearer credential, request body, or a bundle’s contents.

Recover by status

Retry writes deliberately

Safe retries depend on the operation. For example, OTLP ingestion accepts X-Atlan-Ingest-Id to identify the same batch on a retry. Skill uploads refuse content identical to the current version as a duplicate that names the existing skill, so read that skill instead of uploading again; a bundle whose only difference is a file’s permission, such as a script made executable, becomes a new version. Some Registry writes answer their own repeat: revoking an invitation that is already revoked, deactivating an encryption key that is already verified, or withdrawing a release that is already withdrawn answers 200 with the resource’s current state and changes nothing. An invitation that was accepted or has expired, or an encryption key that is pending, retired, or Atlan-managed, still returns 409. Connecting a GitHub installation (POST /github/v1/installations), creating a repository binding (POST /github/v1/installations/{installation_id}/bindings), or adding repositories in a batch (POST /github/v1/installations/{installation_id}/bindings/batch) accepts an optional Idempotency-Key. While the first request with a given key is still running, another request with the same key returns 409 idempotency_conflict instead of connecting or binding a second time. Resend the same key after the first request finishes to receive its result. A batch reports each repository’s outcome in request order: a repository it could not place carries its own status and code in its result while the batch still completes for the rest. Creating an artifact and appending a version to it also accept an optional Idempotency-Key: 1–128 ASCII letters, digits, hyphens, or underscores. Resending the same key with the same request returns the version the first attempt committed, for 24 hours, instead of writing a duplicate. A resend marks its reply: the artifact it returns carries replayed: true, and every other reply — including a write that wrote — leaves the field out. The same key with a different request is refused with 409 idempotency_conflict. The key is scoped to the caller and the operation and never replaces authorization. Creating an artifact of an identity-bearing kind does not accept the key — that create reveals a credential and is never replayed — and a malformed key is a 400. Relationship edges can also be written against the state you reviewed. Every relationship the Registry returns carries an etag, an opaque token over the edge’s stored state. To assert an edge without overwriting a concurrent writer’s change, use the conditional write POST /registry/v1/artifacts/{artifact_kind}/{artifact_id}/relationships/conditional: send the source’s reviewed version handle (source_version_id, a ver_… handle) and ETag (source_etag), the edge state you reviewed as expected_edge, and the ordinary relationship body. expected_edge states either {"state": "absent"} — no row with that edge key exists, including archived rows — or {"state": "present", "etag": "<reviewed etag>"} for the reviewed state of an active or archived edge. The server asserts the edge only while the source and the edge still match what you reviewed. Stale state returns 409 with no side effects, and the 201 response carries the new edge’s etag. To archive exactly the edge you read, use POST /registry/v1/artifacts/{artifact_kind}/{artifact_id}/relationships/archive/conditional with the same source fields, the edge’s rel_type, to_id, and its reviewed expected_etag; it returns 204, and the same 409 when the state moved on. The conditional archive is its own route, so a deployment that does not serve it yet refuses the request — never retry the change through the unconditional archive. Releases and withdrawals have conditional variants too, POST /registry/v1/artifacts/{artifact_kind}/{artifact_id}/releases/conditional and POST /registry/v1/releases/{release_id}/withdraw/conditional; the published reference remains the authority for their request shapes. Do not add a generic retry loop around every POST, PATCH, or archive call. If a write times out or returns a 5xx response, read the intended resource first and retry only when the endpoint contract makes the next action safe.

Get help without exposing data

For a trace issue from aireg, collect its health check and recent log, as described in the aireg CLI reference, and inspect both before sharing. If you exported traces by hand, re-run the export as aireg trace export --log-level debug first, so the log covers it. For a scheduled export, also include aireg job runs. For an HTTP request, share only the operation, status, stable error code, and trace ID where your support process permits it. Keep tokens, full request bodies, and customer content out of tickets and chat.