Skip to content

Error Catalog

OJS defines a canonical error taxonomy with structured error responses, retryability semantics, and protocol-specific mappings. Every error returned by an OJS backend follows a consistent format.

{
"code": "OJS_INVALID_REQUEST",
"message": "Job type is required",
"details": {
"field": "type",
"constraint": "required"
},
"retryable": false,
"doc_url": "https://openjobspec.org/reference/error-codes/#invalid-request"
}
FieldTypeRequiredDescription
codestringYesMachine-readable error code
messagestringYesHuman-readable description
detailsobjectNoAdditional context (field names, constraints, limits)
retryablebooleanYesWhether the client should retry
doc_urlstringNoLink to documentation
CodeHTTPRetryableDescription
OJS_INVALID_REQUEST400NoMalformed request body or missing required fields
OJS_INVALID_PAYLOAD422NoPayload fails schema validation
OJS_SCHEMA_VALIDATION422NoJob envelope fails JSON Schema validation
OJS_ENVELOPE_TOO_LARGE413NoPayload exceeds size limit
CodeHTTPRetryableDescription
OJS_DUPLICATE409NoUnique job constraint violation
OJS_CONFLICT409NoState transition conflict (e.g., cancelling an already completed job)
CodeHTTPRetryableDescription
OJS_NOT_FOUND404NoJob or resource not found
OJS_QUEUE_PAUSED503YesTarget queue is paused
CodeHTTPRetryableDescription
OJS_RATE_LIMITED429YesRate limit exceeded
OJS_BACKEND_ERROR500YesInternal backend failure
OJS_TIMEOUT504YesBackend operation timed out
OJS_UNSUPPORTED501NoOperation not supported by this backend

The retryable field tells clients whether retrying the same request may succeed:

  • Validation errors are never retryable (the request itself is wrong).
  • Conflict errors are generally not retryable (the state needs to change first).
  • Service errors are retryable (the backend may recover).
  • Rate limit errors are retryable (after the Retry-After period).

Handlers can override retryability in error responses. A retryable field in the response takes precedence over the category default.

OJS CodeHTTP StatusgRPC StatusAMQP
OJS_INVALID_REQUEST400INVALID_ARGUMENTChannel error
OJS_NOT_FOUND404NOT_FOUNDbasic.return
OJS_DUPLICATE409ALREADY_EXISTSbasic.return
OJS_RATE_LIMITED429RESOURCE_EXHAUSTEDbasic.nack
OJS_BACKEND_ERROR500INTERNALChannel error
OJS_TIMEOUT504DEADLINE_EXCEEDED

Backends SHOULD preserve recent errors for each job. The error history is available via the job info endpoint and is useful for debugging retry sequences.

{
"id": "01961234-5678-7abc-def0-123456789abc",
"state": "retryable",
"attempt": 3,
"errors": [
{
"attempt": 1,
"type": "connection_timeout",
"message": "Failed to connect to payment gateway",
"occurred_at": "2026-02-15T10:30:00Z"
},
{
"attempt": 2,
"type": "connection_timeout",
"message": "Failed to connect to payment gateway",
"occurred_at": "2026-02-15T10:30:05Z"
}
]
}

Backends SHOULD retain at least the 10 most recent errors per job.

Applications can define custom error codes for domain-specific errors. Custom codes MUST NOT use the OJS_ prefix, which is reserved for specification-defined codes.

{
"code": "PAYMENT_CARD_DECLINED",
"message": "Card ending in 4242 was declined",
"retryable": false
}

Custom codes follow the same structure and retryability rules as OJS-defined codes.