Skip to main content

Canonical Error Codes

Machine-readable, stable, string-valued. Use these exact codes in the error.code field of API and sync error responses (see docs/05-api-design.md).

Never invent new codes in a PR without adding them here.

Format

MELMASTOON.<DOMAIN>.<CODE> — three uppercase, dot-separated segments.

  • <DOMAIN> — the bounded context (e.g., RESERVATION, LOCK, BILLING).
  • <CODE>SCREAMING_SNAKE_CASE describing the failure.

Error response template

{
"error": {
"type": "https://errors.melmastoon.ghasi.io/<domain>/<code>",
"code": "MELMASTOON.<DOMAIN>.<CODE>",
"title": "<short human summary>",
"status": <http status>,
"detail": "<specific explanation, safe to show to user>",
"instance": "<request path>",
"errors": [ { "field": "<optional field>", "code": "<optional sub-code>" } ],
"traceId": "<W3C trace id>",
"requestId": "<ULID>",
"tenantId": "<tnt_...>",
"retriable": <bool>,
"retryAfter": <seconds or null>,
"userMessageKey": "errors.<domain>.<code>",
"docUrl": "https://docs.melmastoon.ghasi.io/errors/<domain>/<code>",
"runbook": "https://runbooks.melmastoon.ghasi.io/<domain>/<code>"
}
}

userMessageKey resolves through the i18n bundle (@ghasi/ui-melmastoon/i18n) so that consumer, tenant booking, and backoffice surfaces show locale-appropriate Pashto / Dari / Arabic / EN / FR text.

Universal rules

  • Never reuse a code across domains.
  • Never change the HTTP status for an existing code.
  • Never include stack traces or internal pointers in detail.
  • Always set traceId + requestId.
  • Always set retriable + retryAfter where a retry is sensible.
  • Never expose whether a resource exists across tenants — return MELMASTOON.GENERAL.RESOURCE_NOT_FOUND, not a 403, for cross-tenant access attempts.

GENERAL

CodeHTTPRetriablei18n keyRoot-cause hintRunbook
MELMASTOON.GENERAL.RESOURCE_NOT_FOUND404noerrors.general.resource_not_foundResource does not exist or is hidden by RLS / tenant scope.general/resource-not-found
MELMASTOON.GENERAL.VALIDATION_FAILED422noerrors.general.validation_failedOne or more request fields failed schema or business validation; see errors[].general/validation
MELMASTOON.GENERAL.PRECONDITION_FAILED412noerrors.general.precondition_failedIf-Match version mismatch on optimistic-concurrency write.general/precondition
MELMASTOON.GENERAL.CROSS_TENANT_REFERENCE422noerrors.general.cross_tenant_referenceAggregate construction or repository call referenced an entity from a different tenant.general/cross-tenant
MELMASTOON.GENERAL.RATE_LIMITED429yeserrors.general.rate_limitedTenant or IP exceeded the rate-limit bucket.general/rate-limit
MELMASTOON.GENERAL.INTERNAL500yeserrors.general.internalUncaught error; alert paged. Check trace.general/internal

IDENTITY

CodeHTTPRetriablei18n keyRoot-cause hintRunbook
MELMASTOON.IDENTITY.INVALID_CREDENTIALS401noerrors.identity.invalid_credentialsUsername/password incorrect or account locked.identity/invalid-credentials
MELMASTOON.IDENTITY.TOKEN_EXPIRED401noerrors.identity.token_expiredAccess token expired; refresh or re-login.identity/token-expired
MELMASTOON.IDENTITY.MFA_REQUIRED401noerrors.identity.mfa_requiredStep-up MFA needed for this operation.identity/mfa
MELMASTOON.IDENTITY.DEVICE_NOT_BOUND403noerrors.identity.device_not_boundDesktop request from an unbound device; complete device pairing.identity/device-binding
MELMASTOON.IDENTITY.PERMISSION_DENIED403noerrors.identity.permission_deniedRBAC/ABAC denied this action for the caller's role.identity/permission
MELMASTOON.IDENTITY.SESSION_REVOKED401noerrors.identity.session_revokedSession was revoked (admin action or device unbinding).identity/session-revoked

TENANT

CodeHTTPRetriablei18n keyRoot-cause hintRunbook
MELMASTOON.TENANT.NOT_FOUND404noerrors.tenant.not_foundX-Tenant-Id header references unknown tenant.tenant/not-found
MELMASTOON.TENANT.SUSPENDED403noerrors.tenant.suspendedTenant suspended for billing or compliance.tenant/suspended
MELMASTOON.TENANT.NOT_A_MEMBER403noerrors.tenant.not_a_memberAuthenticated user is not a member of this tenant.tenant/not-a-member
MELMASTOON.TENANT.PLAN_LIMIT_EXCEEDED402noerrors.tenant.plan_limit_exceededAction would exceed plan limits (rooms, properties, users).tenant/plan-limits
MELMASTOON.TENANT.CONFIGURATION_INVALID422noerrors.tenant.configuration_invalidTenant configuration (currency, locale, tax rules) failed validation.tenant/config

PROPERTY

CodeHTTPRetriablei18n keyRoot-cause hintRunbook
MELMASTOON.PROPERTY.NOT_FOUND404noerrors.property.not_foundProperty ID unknown for this tenant.property/not-found
MELMASTOON.PROPERTY.INACTIVE409noerrors.property.inactiveProperty exists but is inactive (closed for season / suspended).property/inactive
MELMASTOON.PROPERTY.ROOM_TYPE_INVALID422noerrors.property.room_type_invalidRoomType not configured or capacity invalid.property/room-type
MELMASTOON.PROPERTY.ROOM_NOT_AVAILABLE409noerrors.property.room_not_availableSpecific room is OOO/OOS (out-of-order / out-of-service).property/room-status
MELMASTOON.PROPERTY.GEO_INVALID422noerrors.property.geo_invalidLatitude/longitude or address failed validation.property/geo
MELMASTOON.PROPERTY.AMENITY_UNKNOWN422noerrors.property.amenity_unknownAmenity code not in canonical list.property/amenity

RESERVATION

CodeHTTPRetriablei18n keyRoot-cause hintRunbook
MELMASTOON.RESERVATION.OVERBOOKING_BLOCKED409noerrors.reservation.overbooking_blockedConfirming this booking would exceed allocation; another reservation took the last unit.reservation/overbooking
MELMASTOON.RESERVATION.HOLD_EXPIRED410noerrors.reservation.hold_expiredInventory hold expired before the consumer paid.reservation/hold-expired
MELMASTOON.RESERVATION.INVALID_STATE_TRANSITION409noerrors.reservation.invalid_state_transitionCannot transition reservation in its current state (e.g., check-out an unconfirmed booking).reservation/state-machine
MELMASTOON.RESERVATION.GUEST_INFO_INCOMPLETE422noerrors.reservation.guest_info_incompleteRequired guest fields (name, ID document, contact) missing.reservation/guest-info
MELMASTOON.RESERVATION.CHECKIN_WINDOW_VIOLATED409noerrors.reservation.checkin_window_violatedCheck-in attempted outside the configured window without an override.reservation/checkin-window
MELMASTOON.RESERVATION.CANCELLATION_NOT_ALLOWED409noerrors.reservation.cancellation_not_allowedCancellation policy forbids this action (e.g., non-refundable rate past cutoff).reservation/cancellation-policy

INVENTORY

CodeHTTPRetriablei18n keyRoot-cause hintRunbook
MELMASTOON.INVENTORY.ALLOCATION_NOT_FOUND404noerrors.inventory.allocation_not_foundAllocation for the given (property, roomType, date) does not exist.inventory/allocation-not-found
MELMASTOON.INVENTORY.INSUFFICIENT_AVAILABILITY409noerrors.inventory.insufficient_availabilityNot enough units available for the requested date range.inventory/insufficient
MELMASTOON.INVENTORY.STOP_SELL_ACTIVE409noerrors.inventory.stop_sell_activeA stop-sell is active for this date / room type.inventory/stop-sell
MELMASTOON.INVENTORY.MIN_LOS_VIOLATED422noerrors.inventory.min_los_violatedLength of stay below the configured minimum.inventory/min-los
MELMASTOON.INVENTORY.MAX_LOS_VIOLATED422noerrors.inventory.max_los_violatedLength of stay above the configured maximum.inventory/max-los
MELMASTOON.INVENTORY.OVERSELL_DETECTED500noerrors.inventory.oversell_detectedInternal invariant violation: more confirmed reservations than allocation. Page on-call.inventory/oversell

PRICING

CodeHTTPRetriablei18n keyRoot-cause hintRunbook
MELMASTOON.PRICING.RATE_PLAN_NOT_FOUND404noerrors.pricing.rate_plan_not_foundRatePlan does not exist or is not active for the requested date.pricing/rate-plan-not-found
MELMASTOON.PRICING.RATE_PLAN_INACTIVE409noerrors.pricing.rate_plan_inactiveRatePlan is in draft or archived state.pricing/inactive
MELMASTOON.PRICING.CURRENCY_MISMATCH422noerrors.pricing.currency_mismatchQuoted currency does not match property's billing currency.pricing/currency
MELMASTOON.PRICING.QUOTE_EXPIRED410noerrors.pricing.quote_expiredPrice quote expired; re-quote required.pricing/quote-expired
MELMASTOON.PRICING.DERIVATION_FAILED500yeserrors.pricing.derivation_failedPricing engine failed to derive a final amount; check rules cascade.pricing/derivation

BILLING

CodeHTTPRetriablei18n keyRoot-cause hintRunbook
MELMASTOON.BILLING.FOLIO_LOCKED409noerrors.billing.folio_lockedFolio is closed; reopen via supervisor override.billing/folio-locked
MELMASTOON.BILLING.CHARGE_INVALID422noerrors.billing.charge_invalidCharge amount, currency, or category invalid.billing/charge
MELMASTOON.BILLING.INVOICE_ALREADY_ISSUED409noerrors.billing.invoice_already_issuedInvoice already issued for this folio period; void before re-issue.billing/invoice-issued
MELMASTOON.BILLING.TAX_RULE_MISSING422noerrors.billing.tax_rule_missingNo applicable tax rule for jurisdiction × date × charge category.billing/tax-rule
MELMASTOON.BILLING.REFUND_EXCEEDS_BALANCE422noerrors.billing.refund_exceeds_balanceRefund amount exceeds folio balance.billing/refund-balance
MELMASTOON.BILLING.RECONCILIATION_MISMATCH500noerrors.billing.reconciliation_mismatchFolio totals disagree with the underlying ledger; page finance on-call.billing/reconciliation

PAYMENT

CodeHTTPRetriablei18n keyRoot-cause hintRunbook
MELMASTOON.PAYMENT.GATEWAY_TIMEOUT504yeserrors.payment.gateway_timeoutUpstream gateway (PayPal / card processor / MFS) timed out.payment/gateway-timeout
MELMASTOON.PAYMENT.DECLINED402noerrors.payment.declinedIssuer declined the payment instrument.payment/declined
MELMASTOON.PAYMENT.INSUFFICIENT_FUNDS402noerrors.payment.insufficient_fundsInsufficient funds on the instrument.payment/insufficient-funds
MELMASTOON.PAYMENT.INTENT_NOT_FOUND404noerrors.payment.intent_not_foundPaymentIntent ID unknown or expired.payment/intent-not-found
MELMASTOON.PAYMENT.WEBHOOK_SIGNATURE_INVALID401noerrors.payment.webhook_signature_invalidWebhook signature mismatch — possible spoof or rotated secret.payment/webhook-signature
MELMASTOON.PAYMENT.CASH_RECONCILIATION_PENDING202yeserrors.payment.cash_reconciliation_pendingCash-on-arrival not yet reconciled by front desk.payment/cash-reconciliation

HOUSEKEEPING

CodeHTTPRetriablei18n keyRoot-cause hintRunbook
MELMASTOON.HOUSEKEEPING.TASK_NOT_FOUND404noerrors.housekeeping.task_not_foundTask ID unknown for this property.housekeeping/task-not-found
MELMASTOON.HOUSEKEEPING.ROOM_STATE_CONFLICT409noerrors.housekeeping.room_state_conflictRoom state changed between task assignment and update (e.g., guest checked back in).housekeeping/room-state
MELMASTOON.HOUSEKEEPING.STAFF_UNAVAILABLE409noerrors.housekeeping.staff_unavailableAssigned staff member is off-shift.housekeeping/staff-unavailable
MELMASTOON.HOUSEKEEPING.TASK_ALREADY_COMPLETED409noerrors.housekeeping.task_already_completedTask already marked completed.housekeeping/already-completed
MELMASTOON.HOUSEKEEPING.SCHEDULE_OVERFLOW422noerrors.housekeeping.schedule_overflowScheduling exceeds shift capacity.housekeeping/schedule-overflow

MAINTENANCE

CodeHTTPRetriablei18n keyRoot-cause hintRunbook
MELMASTOON.MAINTENANCE.TICKET_NOT_FOUND404noerrors.maintenance.ticket_not_foundMaintenance ticket unknown.maintenance/ticket-not-found
MELMASTOON.MAINTENANCE.ROOM_BLOCKED409noerrors.maintenance.room_blockedRoom blocked by an open ticket; cannot sell until cleared.maintenance/room-blocked
MELMASTOON.MAINTENANCE.SEVERITY_INVALID422noerrors.maintenance.severity_invalidSeverity outside allowed enum.maintenance/severity
MELMASTOON.MAINTENANCE.ASSIGNMENT_FAILED409noerrors.maintenance.assignment_failedNo available technician matches the required skill.maintenance/assignment

NOTIFICATION

CodeHTTPRetriablei18n keyRoot-cause hintRunbook
MELMASTOON.NOTIFICATION.TEMPLATE_NOT_FOUND404noerrors.notification.template_not_foundTemplate ID/locale combination not registered.notification/template-not-found
MELMASTOON.NOTIFICATION.CHANNEL_DISABLED409noerrors.notification.channel_disabledRecipient opted out of this channel (email/SMS/push).notification/channel-disabled
MELMASTOON.NOTIFICATION.PROVIDER_UNAVAILABLE502yeserrors.notification.provider_unavailableUpstream email/SMS/push provider failed.notification/provider
MELMASTOON.NOTIFICATION.RECIPIENT_INVALID422noerrors.notification.recipient_invalidRecipient address/phone failed validation.notification/recipient
MELMASTOON.NOTIFICATION.RATE_LIMITED429yeserrors.notification.rate_limitedPer-recipient or per-tenant throttle reached.notification/rate-limit

LOCK

CodeHTTPRetriablei18n keyRoot-cause hintRunbook
MELMASTOON.LOCK.VENDOR_UNREACHABLE502yeserrors.lock.vendor_unreachableLock vendor API unreachable (TTLock / Salto / Assa Abloy). Falls back to mechanical key flow.lock/vendor-unreachable
MELMASTOON.LOCK.KEY_ISSUE_FAILED502yeserrors.lock.key_issue_failedVendor returned an error issuing the key credential.lock/key-issue
MELMASTOON.LOCK.KEY_REVOKE_FAILED502yeserrors.lock.key_revoke_failedVendor returned an error revoking the key credential; security alert raised.lock/key-revoke
MELMASTOON.LOCK.DEVICE_NOT_PAIRED409noerrors.lock.device_not_pairedLock device not paired to the property; complete pairing in backoffice.lock/device-pairing
MELMASTOON.LOCK.CREDENTIAL_EXPIRED410noerrors.lock.credential_expiredKey credential expired (date range past valid_until).lock/credential-expired
MELMASTOON.LOCK.CARD_ENCODER_OFFLINE503yeserrors.lock.card_encoder_offlineFront-desk card encoder is offline; queue for retry.lock/encoder-offline

SYNC

CodeHTTPRetriablei18n keyRoot-cause hintRunbook
MELMASTOON.SYNC.CURSOR_OUT_OF_RANGE410noerrors.sync.cursor_out_of_rangeSync cursor too old; client must perform full rebase pull.sync/cursor-out-of-range
MELMASTOON.SYNC.MUTATION_REJECTED409noerrors.sync.mutation_rejectedOffline mutation violates a server-authoritative invariant.sync/mutation-rejected
MELMASTOON.SYNC.CONFLICT_DETECTED409noerrors.sync.conflict_detectedConflict detected; resolution required per aggregate's policy.sync/conflict
MELMASTOON.SYNC.IDEMPOTENCY_KEY_REUSED409noerrors.sync.idempotency_key_reusedSame Idempotency-Key used with a different body.sync/idempotency-reuse
MELMASTOON.SYNC.DEVICE_UNBOUND403noerrors.sync.device_unboundDevice binding revoked; re-pair the desktop client.sync/device-unbound
MELMASTOON.SYNC.PAYLOAD_TOO_LARGE413noerrors.sync.payload_too_largePush batch exceeds the per-call size budget.sync/payload-too-large

AI

CodeHTTPRetriablei18n keyRoot-cause hintRunbook
MELMASTOON.AI.REFUSED_SAFETY422noerrors.ai.refused_safetyPre-call or post-call safety classifier blocked the request.ai/refused-safety
MELMASTOON.AI.REFUSED_BUDGET429yeserrors.ai.refused_budgetTenant or purpose AI budget exceeded for this period.ai/refused-budget
MELMASTOON.AI.PROVIDER_UNAVAILABLE502yeserrors.ai.provider_unavailableUpstream LLM/embedding provider failed.ai/provider-unavailable
MELMASTOON.AI.HITL_REQUIRED403noerrors.ai.hitl_requiredAction requires human-in-the-loop approval before commit.ai/hitl-required
MELMASTOON.AI.PROVENANCE_MISSING422noerrors.ai.provenance_missingPersistence attempt for an AI artifact without AIProvenance VO.ai/provenance-missing
MELMASTOON.AI.OUTPUT_INVALID502yeserrors.ai.output_invalidStructured output failed schema validation after repair attempt.ai/output-invalid

THEME

CodeHTTPRetriablei18n keyRoot-cause hintRunbook
MELMASTOON.THEME.NOT_FOUND404noerrors.theme.not_foundTheme ID unknown for this tenant.theme/not-found
MELMASTOON.THEME.TOKEN_INVALID422noerrors.theme.token_invalidDesign token failed contrast or schema validation.theme/token-invalid
MELMASTOON.THEME.LAYOUT_PRESET_UNKNOWN422noerrors.theme.layout_preset_unknownLayout preset not in canonical registry.theme/layout-preset
MELMASTOON.THEME.RTL_VARIANT_MISSING422noerrors.theme.rtl_variant_missingRTL variant not provided for an asset that requires one.theme/rtl-variant
MELMASTOON.THEME.ASSET_TOO_LARGE413noerrors.theme.asset_too_largeTheme asset exceeds size budget (logo/hero/font).theme/asset-size
CodeHTTPRetriablei18n keyRoot-cause hintRunbook
MELMASTOON.SEARCH.QUERY_INVALID422noerrors.search.query_invalidQuery string failed parsing or budget.search/query-invalid
MELMASTOON.SEARCH.GEO_OUT_OF_BOUNDS422noerrors.search.geo_out_of_boundsBounding box / radius outside supported limits.search/geo-bounds
MELMASTOON.SEARCH.INDEX_UNAVAILABLE503yeserrors.search.index_unavailableSearch index reindexing or degraded; serve cached results.search/index-unavailable
MELMASTOON.SEARCH.RANKER_UNAVAILABLE502yeserrors.search.ranker_unavailablePersonalization ranker offline; fallback to deterministic ranking.search/ranker-unavailable
MELMASTOON.SEARCH.PAGE_OUT_OF_RANGE422noerrors.search.page_out_of_rangeCursor refers to an expired or invalid page.search/page

BFF

CodeHTTPRetriablei18n keyRoot-cause hintRunbook
MELMASTOON.BFF.UPSTREAM_TIMEOUT504yeserrors.bff.upstream_timeoutA downstream service did not respond within the BFF deadline.bff/upstream-timeout
MELMASTOON.BFF.UPSTREAM_UNAVAILABLE502yeserrors.bff.upstream_unavailableA downstream service is down; partial response served if possible.bff/upstream-unavailable
MELMASTOON.BFF.AGGREGATE_FAILED500yeserrors.bff.aggregate_failedOne or more parallel calls failed and the aggregate cannot be assembled.bff/aggregate-failed
MELMASTOON.BFF.SURFACE_MISMATCH403noerrors.bff.surface_mismatchCaller surface (consumer / tenant booking / backoffice) does not match this BFF.bff/surface-mismatch
MELMASTOON.BFF.SCHEMA_DRIFT502noerrors.bff.schema_driftDownstream response did not match the BFF's expected schema; alert paged.bff/schema-drift