Errors

Vision errors are designed for safe diagnosis without revealing whether a credential, private record, grant, key, or policy object exists. Read the target App's declared schema; the preview contracts do not yet share one identical envelope.

Envelope

{
  "error": {
    "code": "invalid_client",
    "message": "Client authentication failed.",
    "requestId": "req_...",
    "retryable": false
  }
}

The Vision Core resource envelope carries a stable code, safe message, request ID, and server retry decision. OAuth token exchange is a protocol exception and returns OAuth-compatible error and optional error_description fields instead.

Status codes

  • Name
    400
    Description
    Malformed or unsupported request.
  • Name
    401
    Description

    Missing, invalid, expired, or revoked authentication.

  • Name
    403
    Description

    Valid identity without the required scope or entitlement.

  • Name
    404
    Description

    Resource unavailable or intentionally non-disclosed.

  • Name
    429
    Description

    A shared rate policy denied the request. Respect Retry-After.

  • Name
    503
    Description

    A required dependency is unavailable. Retry only when retryable is true.

409 and 422 are also used by Apps that expose stateful commands, optimistic versions, idempotency conflicts, or domain validation. The operation page is authoritative for the statuses it can return.

App differences

  • Name
    Vision Core
    Description

    Resource errors use the nested error envelope above. Token exchange uses the OAuth error shape.

  • Name
    CRM
    Description

    CRM errors include a schema version, stable uppercase code, retryable flag, UUID correlation ID, bounded field issues, and optional current-version conflict detail.

  • Name
    Calendar
    Description

    Calendar declares operation-specific errors for authentication, authorization, validation, missing resources, conflicts, and dependency failure.

  • Name
    Accounting
    Description

    Accounting distinguishes validation, authorization, missing references, conflicts, and unprocessable domain requests where declared.

Do not normalize away App-specific details before your application has recorded the safe correlation evidence it needs. Do not expose internal error bodies directly to an end user.

Retry decisions

FailureDefault action
Invalid request or field issueCorrect the request; do not retry unchanged
Invalid or expired tokenObtain a valid token once; stop if the replacement is denied
Missing scope, entitlement, role, or record permissionChange the approved grant or workflow; do not retry
Not found or non-disclosedStop unless the business workflow explicitly permits later reconciliation
Idempotency or stale-version conflictRead current state and reconcile; do not blind-retry
429 with Retry-AfterWait for the supplied interval, add jitter, remain inside a bounded retry budget
Dependency unavailable and retryable: trueRetry with exponential backoff and a total deadline
Client timeout on a mutationTreat outcome as unknown; reconcile by idempotency key or receipt

Handling example

Structured Vision API error

type VisionErrorBody = {
  error?: {
    code?: string
    message?: string
    requestId?: string
    retryable?: boolean
    details?: unknown
  }
}

export class VisionApiError extends Error {
  constructor(
    readonly status: number,
    readonly code: string,
    readonly requestId: string | null,
    readonly retryable: boolean,
    message: string,
  ) {
    super(message)
  }
}

async function parseVisionResponse(response: Response) {
  const requestId = response.headers.get('x-request-id')
  const body = (await response.json().catch(() => ({}))) as VisionErrorBody

  if (response.ok) return body

  throw new VisionApiError(
    response.status,
    body.error?.code ?? 'unparseable_error',
    body.error?.requestId ?? requestId,
    body.error?.retryable ?? false,
    body.error?.message ?? 'The Vision API request failed.',
  )
}

Do not mark every 5xx retryable in client code. The resource server's decision and the operation's idempotency semantics matter.

Troubleshooting

Capture the environment, App, contract version, operation, status, stable error code, safe request/correlation ID, and timestamp. Confirm the exact origin, token audience, App entitlement, workspace, scope, and identity class. For validation errors, compare field casing, media type, enum values, nullability, timestamp offsets, and unknown properties against the operation schema.

Never send a client secret, bearer token, webhook secret, private key, cookie, complete private payload, or production database identifier in support material.

Request IDs

Vision Core returns x-request-id; CRM commonly exposes a UUID correlation ID in its error model. Preserve the identifier exactly as returned. A client-generated identifier is useful only when the server accepts and echoes it.