API Error Codes

Overview

All API errors follow a consistent format with error codes for programmatic handling.

Error Response Format

interface ApiErrorResponse {
  success: false;
  error: {
    code: string;           // Machine-readable error code
    message: string;        // Human-readable message
    details?: object;       // Additional context
    validationErrors?: ValidationError[];
  };
  meta: {
    requestId: string;
    timestamp: string;
  };
}

interface ValidationError {
  field: string;
  message: string;
  code: string;
}

Error Code Categories

PrefixCategoryHTTP Status Range
AUTH_Authentication401
PERM_Authorization/Permission403
VAL_Validation400
RES_Resource404, 409
ENV_Environment422
REL_Release422
PROM_Promotion422
DEPLOY_Deployment422
GATE_Gate422
AGT_Agent422
INT_Integration422
WF_Workflow422
SYS_System500

Authentication Errors (401)

CodeMessageDescription
AUTH_TOKEN_MISSINGAuthentication token requiredNo token provided
AUTH_TOKEN_INVALIDInvalid authentication tokenToken cannot be parsed
AUTH_TOKEN_EXPIREDAuthentication token expiredToken has expired
AUTH_TOKEN_REVOKEDAuthentication token revokedToken has been revoked
AUTH_AGENT_CERT_INVALIDInvalid agent certificateAgent mTLS cert invalid
AUTH_AGENT_CERT_EXPIREDAgent certificate expiredAgent cert has expired
AUTH_API_KEY_INVALIDInvalid API keyAPI key not recognized

Permission Errors (403)

CodeMessageDescription
PERM_DENIEDPermission deniedGeneric permission denial
PERM_RESOURCE_DENIEDAccess to resource deniedCannot access specific resource
PERM_ACTION_DENIEDAction not permittedCannot perform specific action
PERM_SCOPE_DENIEDOutside permitted scopeAction outside user’s scope
PERM_SOD_VIOLATIONSeparation of duties violationSoD prevents action
PERM_SELF_APPROVALCannot approve own requestSelf-approval not allowed
PERM_TENANT_MISMATCHTenant mismatchResource belongs to different tenant

Validation Errors (400)

CodeMessageDescription
VAL_REQUIRED_FIELDRequired field missingField is required
VAL_INVALID_FORMATInvalid field formatField format incorrect
VAL_INVALID_VALUEInvalid field valueValue not in allowed set
VAL_TOO_LONGField value too longExceeds max length
VAL_TOO_SHORTField value too shortBelow min length
VAL_INVALID_UUIDInvalid UUID formatNot a valid UUID
VAL_INVALID_DIGESTInvalid digest formatNot a valid OCI digest
VAL_INVALID_SEMVERInvalid semver formatNot valid semantic version
VAL_INVALID_JSONInvalid JSONRequest body not valid JSON
VAL_SCHEMA_MISMATCHSchema validation failedDoesn’t match schema

Resource Errors (404, 409)

CodeMessageHTTPDescription
RES_NOT_FOUNDResource not found404Generic not found
RES_ENVIRONMENT_NOT_FOUNDEnvironment not found404Environment doesn’t exist
RES_RELEASE_NOT_FOUNDRelease not found404Release doesn’t exist
RES_PROMOTION_NOT_FOUNDPromotion not found404Promotion doesn’t exist
RES_TARGET_NOT_FOUNDTarget not found404Target doesn’t exist
RES_AGENT_NOT_FOUNDAgent not found404Agent doesn’t exist
RES_CONFLICTResource conflict409Resource state conflict
RES_ALREADY_EXISTSResource already exists409Duplicate resource
RES_VERSION_CONFLICTVersion conflict409Optimistic lock failure

Environment Errors (422)

CodeMessageDescription
ENV_FROZENEnvironment is frozenDeployment blocked by freeze window
ENV_FREEZE_ACTIVEActive freeze windowCannot modify during freeze
ENV_INVALID_ORDERInvalid environment orderOrder index conflict
ENV_CIRCULAR_PROMOTIONCircular promotion pathAuto-promote creates cycle
ENV_QUOTA_EXCEEDEDEnvironment quota exceededMax environments reached

Release Errors (422)

CodeMessageDescription
REL_ALREADY_FINALIZEDRelease already finalizedCannot modify finalized release
REL_NOT_READYRelease not readyRelease not in ready state
REL_DIGEST_MISMATCHDigest mismatchResolved digest differs
REL_TAG_NOT_FOUNDTag not found in registryCannot resolve tag
REL_COMPONENT_MISSINGComponent not foundReferenced component missing
REL_INVALID_STATUS_TRANSITIONInvalid status transitionStatus change not allowed
REL_DEPRECATEDRelease deprecatedCannot promote deprecated release

Promotion Errors (422)

CodeMessageDescription
PROM_ALREADY_EXISTSPromotion already pendingDuplicate promotion request
PROM_NOT_PENDINGPromotion not pendingCannot approve/reject
PROM_ALREADY_APPROVEDPromotion already approvedAlready approved
PROM_ALREADY_REJECTEDPromotion already rejectedAlready rejected
PROM_ALREADY_CANCELLEDPromotion already cancelledAlready cancelled
PROM_DEPLOYINGPromotion is deployingCannot cancel during deploy
PROM_INVALID_STATEInvalid promotion stateState doesn’t allow action
PROM_APPROVER_REQUIREDAdditional approvers requiredInsufficient approvals
PROM_SKIP_ENVIRONMENTCannot skip environmentsMust promote sequentially

Deployment Errors (422)

CodeMessageDescription
DEPLOY_IN_PROGRESSDeployment in progressAnother deployment running
DEPLOY_NO_TARGETSNo targets availableNo targets in environment
DEPLOY_TARGET_UNHEALTHYTarget unhealthyTarget failed health check
DEPLOY_AGENT_UNAVAILABLEAgent unavailableRequired agent offline
DEPLOY_ARTIFACT_MISSINGDeployment artifact missingRequired artifact not found
DEPLOY_TIMEOUTDeployment timeoutExceeded timeout
DEPLOY_PULL_FAILEDImage pull failedCannot pull container image
DEPLOY_DIGEST_VERIFICATION_FAILEDDigest verification failedImage tampered
DEPLOY_HEALTH_CHECK_FAILEDHealth check failedPost-deploy health failed
DEPLOY_ROLLBACK_IN_PROGRESSRollback in progressAlready rolling back
DEPLOY_NOTHING_TO_ROLLBACKNothing to rollbackNo previous deployment

Deployment Failure Anatomy (execution failures)

The error codes above are pre-deploy 4xx API responses. Once a deploy passes gating and a deployment job runs, an execution failure is described by a structured failure anatomy attached to the job and to each failed target — not a raw exception string. It is surfaced on the deployment DTO (GET /api/v1/release-orchestrator/deployments/{id}) both job-level (failureAnatomy) and per-target (targets[].failureAnatomy), and rendered in the console deployment monitor.

interface DeploymentFailureAnatomy {
  stage: string;        // where it failed: artifact-generation | bundle-assembly | strategy-planning
                        //   | traffic-gate | preflight | execution | health-probe | retry-prep | rollback
  category: string;     // typed cause (see below)
  reason: string;       // stable machine-readable slug
  plainReason: string;  // operator-facing one-line cause (the lead)
  detail: string;       // the raw technical string (exception "TypeName: message"), preserved verbatim
  action: string;       // plain-language remediation guidance
  actionPath: string | null; // a real endpoint to act on, or null (never a dead link)
  retryable: boolean;   // true ONLY for genuinely transient causes
}

Categories: SecretResolution, RegistryUnreachable, AgentUnassigned, AgentOffline, Timeout, TargetNotFound, UnsupportedTarget, NoHealthyTargets, DependencyGraph, PreflightFailed, HealthCheckFailed, NoTargetsEnrolled, StrategyPlanIncomplete, StrategyGateHalted, RollbackNotEligible, Unclassified.

Honesty invariants (binding):

Deployment Preflight (pre-launch readiness)

Before a deploy launches, a preflight runs a tri-state readiness checklist (GET /api/v1/release-orchestrator/releases/{releaseId}/deploy-preflight?environmentId=), and the launch chokepoint enforces it after the un-waivable security floor.

interface PreflightReport {
  releaseId: string; environment: string | null;
  armed: boolean;            // true iff zero hard fails (unknowns do NOT dis-arm)
  hasHardFail: boolean;
  failedCheckKeys: string[];
  checks: PreflightCheck[];
}
interface PreflightCheck {
  key: string;               // digest-pinned | image-resolvable | target-ready | secret-resolvable
  title: string;
  status: 'pass' | 'fail' | 'unknown';
  detail: string;
  anatomy: DeploymentFailureAnatomy | null;  // present on a fail (reuses the D1 anatomy shape)
}

Honesty invariants (binding):

Landing Verification & Deployment Attestation (post-deploy)

After a deploy completes, the pipeline verifies the landing and — only on a fully-verified landing — emits a deployment attestation. Both surface on the deployment DTO (landingVerification job-level + targets[].landing per-target; deploymentAttestationRef when attested) and light the console custody Deploy step.

Landing verdict (per target, honest tri-state): compares the digest the agent actually reported deploying (manifestDigest, corroborated by the EAD observed-running-digest) against the release’s gated digest.

Deployment attestation (binding honesty): a deployment-kind in-toto attestation (predicate https://stellaops.dev/predicates/deployment@v1) is signed and anchored in the transparency log only when the job is Completed AND every target landed verified. The honesty gate returns before touching the signer/submitter otherwise. It lights custody Deploy = SIGNED (recorded) → PROVEN (verified via POST /api/v1/rekor/verify, the same path the Scan step uses). Absent a real attestation, Deploy stays RECORDED/MISSING — never a fabricated PROVEN. Signing/submission failure is fail-open (the deploy already succeeded): the landing verdict is still recorded, just without an attestation ref.

Deployment Strategy Plan (honesty preview)

A deployment strategy (rolling / all_at_once / blue_green / canary) is a target-batching planner. GET /api/v1/release-orchestrator/releases/{releaseId}/deploy-plan?strategy=&environmentId= previews what the requested strategy will actually do for a release’s real target count — it runs the strategy’s real plan and returns the phases verbatim plus honest caveats, so a requested strategy never implies behaviour it will not deliver.

{ "strategy": "canary", "requestedStrategy": "canary", "targetCount": 1,
  "phases": [ { "index": 0, "targetCount": 1, "kind": "all-at-once" } ],
  "effectiveBehaviour": "With 1 target, 'canary' runs as a single all-at-once deploy …",
  "caveats": [ "single-target-collapse", "no-traffic-management" ] }

Honesty invariants (binding):

Watch / Drift (post-landing)

After landing, the deploy is watched: deploy agents report the container image digests they OBSERVE running, and the orchestrator compares them against the release’s approved/deployed digests. Tenant-scoped status, drift, and digest-location reads (GET /api/v1/release-orchestrator/estate/status|drift and GET /api/v1/release-orchestrator/estate/digest/{digest}) accept either release:read or orch:read; deviations and the other Estate reads remain orch:read-only.

// GET /estate/status
{ "deployedComponents": 8,
  "drift": { "total": 1, "drift": 1, "inSync": 0, "unobserved": 0, "observingAgents": 1 },
  "deviations": { "count": 0 } }

The signal surfaces in the console as a needs-you “components in drift” item, an estate-matrix drift chip, and the custody Run-stage rail.

Honesty invariants (binding):

Gate Errors (422)

CodeMessageDescription
GATE_EVALUATION_FAILEDGate evaluation failedGate cannot be evaluated
GATE_SECURITY_BLOCKEDBlocked by security gateSecurity policy violation
GATE_POLICY_BLOCKEDBlocked by policy gateCustom policy violation
GATE_APPROVAL_BLOCKEDBlocked pending approvalAwaiting approval
GATE_TIMEOUTGate evaluation timeoutEvaluation exceeded timeout

Agent Errors (422)

CodeMessageDescription
AGT_REGISTRATION_FAILEDAgent registration failedCannot register agent
AGT_TOKEN_INVALIDInvalid registration tokenBad or expired token
AGT_TOKEN_USEDRegistration token already usedOne-time token reused
AGT_CERTIFICATE_FAILEDCertificate issuance failedCannot issue certificate
AGT_OFFLINEAgent offlineAgent not responding
AGT_CAPABILITY_MISSINGMissing capabilityAgent lacks required capability
AGT_TASK_FAILEDTask execution failedAgent task failed
AGT_HEARTBEAT_TIMEOUTHeartbeat timeoutAgent heartbeat overdue

Integration Errors (422)

CodeMessageDescription
INT_CONNECTION_FAILEDConnection failedCannot connect to integration
INT_AUTH_FAILEDAuthentication failedIntegration auth failed
INT_RATE_LIMITEDRate limitedIntegration rate limit hit
INT_TIMEOUTIntegration timeoutRequest timeout
INT_INVALID_RESPONSEInvalid responseUnexpected response format
INT_RESOURCE_NOT_FOUNDExternal resource not foundRegistry/SCM resource missing

Workflow Errors (422)

CodeMessageDescription
WF_TEMPLATE_NOT_FOUNDWorkflow template not foundTemplate doesn’t exist
WF_TEMPLATE_INVALIDInvalid workflow templateTemplate validation failed
WF_CYCLE_DETECTEDCycle detected in workflowDAG contains cycle
WF_STEP_FAILEDWorkflow step failedStep execution failed
WF_ALREADY_RUNNINGWorkflow already runningDuplicate workflow run
WF_INVALID_STATEInvalid workflow stateCannot perform action
WF_EXPRESSION_ERRORExpression evaluation errorBad expression

System Errors (500)

CodeMessageDescription
SYS_INTERNAL_ERRORInternal server errorUnexpected error
SYS_DATABASE_ERRORDatabase errorDatabase operation failed
SYS_STORAGE_ERRORStorage errorStorage operation failed
SYS_VAULT_ERRORVault errorSecret retrieval failed
SYS_QUEUE_ERRORQueue errorMessage queue failed
SYS_SERVICE_UNAVAILABLEService unavailableDependency unavailable
SYS_OVERLOADEDSystem overloadedCapacity exceeded

Example Error Responses

Validation Error

{
  "success": false,
  "error": {
    "code": "VAL_REQUIRED_FIELD",
    "message": "Validation failed",
    "validationErrors": [
      {
        "field": "releaseId",
        "message": "Release ID is required",
        "code": "VAL_REQUIRED_FIELD"
      },
      {
        "field": "targetEnvironmentId",
        "message": "Invalid UUID format",
        "code": "VAL_INVALID_UUID"
      }
    ]
  },
  "meta": {
    "requestId": "req-12345",
    "timestamp": "2026-01-10T14:30:00Z"
  }
}

Permission Error

{
  "success": false,
  "error": {
    "code": "PERM_SOD_VIOLATION",
    "message": "Separation of duties violation: requester cannot approve their own promotion",
    "details": {
      "promotionId": "promo-uuid",
      "requesterId": "user-uuid",
      "approverId": "user-uuid",
      "environmentId": "env-uuid",
      "requiresSoD": true
    }
  },
  "meta": {
    "requestId": "req-12345",
    "timestamp": "2026-01-10T14:30:00Z"
  }
}

Gate Block Error

{
  "success": false,
  "error": {
    "code": "GATE_SECURITY_BLOCKED",
    "message": "Promotion blocked by security gate",
    "details": {
      "gateName": "security-gate",
      "releaseId": "rel-uuid",
      "targetEnvironment": "production",
      "violations": [
        {
          "type": "critical_vulnerability",
          "count": 3,
          "threshold": 0
        }
      ]
    }
  },
  "meta": {
    "requestId": "req-12345",
    "timestamp": "2026-01-10T14:30:00Z"
  }
}

References