Skip to content

Errors

Every error response from the jtWMS API, 4xx or 5xx, is an RFC 9457 problem details object, sent with the content type application/problem+json.

HTTP/1.1 409 Conflict
Content-Type: application/problem+json
X-Correlation-Id: 3f2504e0-4f89-11d3-9a0c-0305e82c3301
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.10",
"title": "Conflict",
"status": 409,
"detail": "A product with SKU 'PAL-0042' already exists (SKUs are compared ignoring case).",
"errorCode": "sku_conflict",
"traceId": "00-6f1c0a9d2b6e4c1f8a3b5d7e9f0a1b2c-4d5e6f7a8b9c0d1e-00",
"correlationId": "3f2504e0-4f89-11d3-9a0c-0305e82c3301"
}
Member Present Meaning
status Always The HTTP status code.
title Always A short summary of the status, such as Not Found or Conflict.
type Usually A URI for the problem type. By default, the RFC 9110 section for the status.
detail When there is a message A human-readable explanation of this error, suitable to show to a user.
errorCode When the error has one A stable, machine-readable code. See Error codes.
traceId Always The request’s trace identifier.
correlationId Always The request’s correlation ID. See Correlation IDs.

Some errors add members that help you act on them, such as maxApiKeys, childIds or barcodes. They sit beside the standard members, in camelCase.

A request that fails validation gets 400 Bad Request with an errors member. Its keys are the paths of the invalid fields, in PascalCase as the server names them, including array indexes; its values are lists of messages.

{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {
"Name": ["'Name' must not be empty."],
"UnitsOfMeasure[1].Barcodes[0].Value": ["'Value' must be a GTIN of 8, 12, 13 or 14 digits with a valid check digit."]
},
"traceId": "00-6f1c0a9d2b6e4c1f8a3b5d7e9f0a1b2c-4d5e6f7a8b9c0d1e-00",
"correlationId": "3f2504e0-4f89-11d3-9a0c-0305e82c3301"
}

Map the keys to your own fields case-insensitively. A validation error can also carry an errorCode, as the API key scope errors do.

Status Meaning
400 The request is invalid. Fix it before retrying.
401 The request isn’t authenticated, or its token or key is no longer valid. See Authentication.
403 The caller lacks the permission the endpoint needs, or the tenant’s plan lacks the feature. See Permissions.
404 The resource doesn’t exist, has been deleted, or belongs to another tenant. These cases aren’t told apart.
409 The request conflicts with the resource’s current state. See Concurrency and deletes.
422 The request is well formed but can’t be processed (sign-up with a registered email).
429 A rate limit was exceeded. See Rate limits.
500 An unexpected error. The detail doesn’t include internal information; quote the correlationId to support.
502, 504 jtWMS couldn’t reach the service that handles the route, or it didn’t answer in time. Retry later.
503 A dependency is briefly unavailable. Retry after the Retry-After seconds.
errorCode Status Meaning
token_revoked 401 The user’s access changed since the token was issued. Refresh the session, or sign in again if the refresh fails.
invalid_api_key 401 The API key is unknown, revoked or expired, or its tenant is inactive.
auth_unavailable 503 The API key couldn’t be checked just now. Retry after Retry-After (5 seconds).
feature_not_entitled 403 The tenant’s plan doesn’t include the feature the route needs.
permission_not_held 403 A role, invite or role change would hand out permissions you don’t hold. They are listed in permissions.
burst_limit_exceeded 429 Too many requests in a short period. Retry after Retry-After.
rate_limit_exceeded 429 The tenant’s daily request quota is used up. Retry after Retry-After.
concurrency_conflict 409 Another request changed the same data at the same time. Nothing was saved. Re-read and retry.
api_key_permission_unknown 400 A requested API key permission isn’t registered or is inactive.
api_key_permission_not_held 400 You don’t hold a permission you asked to give an API key.
api_key_limit_reached 409 The tenant has as many API keys as its plan allows (maxApiKeys).
system_role_immutable 409 System roles can’t be deleted, renamed or edited. Copy the role instead.
user_inactive 409 The user is deactivated. Reactivate them first.
invite_role_unknown 400 An invite names a role that isn’t one of the tenant’s roles.
INVITE_NOT_FOUND, INVITE_INVALID 404 The invite link is unknown, expired, revoked or already used.
USER_ALREADY_EXISTS 409 A user with this email already exists.
email_in_use 409 An invite names, or is accepted for, an email that belongs to a jtWMS account elsewhere.
invite_daily_limit 429 The organisation has sent its daily limit of invites (200 in 24 hours). Nothing was saved.
sandbox_not_found 404 The organisation has no sandbox.
sandbox_exists 409 The organisation already has a sandbox. Reset it to start again.
sandbox_reset_limit 429 The organisation has created as many sandboxes today (creates and resets) as it can.
not_allowed_in_sandbox 409 The action can’t be taken inside a sandbox: inviting people, changing plan, or managing a sandbox.
sandbox_plan_reserved 409 A plan or add-on change would give a sandbox other entitlements than the sandbox plan’s, or move another tenant onto it.
EMAIL_ALREADY_EXISTS 422 Sign-up with an email that is already registered.
reset_token_invalid 400 The password reset link is invalid or has expired. Ask for a new one.
product_not_found 404 No product matches the lookup, or an inventory write names a product that isn’t known (listed in productIds).
product_already_active 409 The product is already active.
product_already_inactive 409 The product is already inactive.
sku_conflict 409 Another product already has this SKU (ignoring case).
barcode_conflict 409 Barcodes in the request are already assigned to another product. They are listed in barcodes.
facility_not_found 404 An inventory request names a facility that isn’t known.
location_not_found 404 An inventory write names a location that isn’t known or is in another facility (listed in locationIds).
position_not_found 404 The stock position isn’t in this facility, or was emptied. For a move, hold or release by serial numbers, the serials not on hand in the facility are listed in serials.
lpn_not_found 404 The license plate isn’t in this facility, or was deleted (listed in lpnIds).
code_not_found 404 A lookup’s code is no license plate, location, barcode or SKU in this facility.
transaction_not_found 404 The stock transaction isn’t in this facility.
allocation_not_found 404 The allocation isn’t in this facility.
allocation_line_not_found 404 A pick names a line that isn’t the allocation’s, or serial numbers no line of it holds (listed in serials).
lpn_nesting_invalid 400 A license plate can’t go there: only a case or tote sits on another license plate, and only on a pallet. The field is listed in errors.
nothing_to_move 400 The move’s or pick’s target is where the stock or license plate already is.
stock_rules_violated 400 A line breaks its product’s rules: an unknown unit of measure, a missing or unwanted lot, expiry date or serials, or a quantity too large. The fields are listed in errors.
product_blocked, location_blocked, facility_blocked 409 Stock can’t be received or adjusted into a product, location or facility that isn’t active, and nothing can be moved or picked into, or a license plate created at, a location or facility that isn’t. Nothing of a product that isn’t active, or in a facility that isn’t, can be allocated. The reasons are in blockedReasons.
lpn_code_conflict 409 Another license plate in the facility already has this code (ignoring case).
lpn_not_empty 409 The license plate, or one on it, still holds stock (listed in lpnIds). Move or adjust the stock out first.
lpn_location_mismatch 409 The license plate named isn’t at the location named with it (its locationId is included).
lot_expiry_mismatch 409 The lot already exists with another expiry date (in expiryDate).
serial_conflict 409 Serial numbers in the request are already on hand. They are listed in serials.
insufficient_stock 409 An adjustment, move or hold would take a position below zero (its quantity is included), or an allocation asks for more than is available (its availableQuantity and requestedQuantity are included).
stock_allocated 409 An adjustment, move or hold would take a position below its allocated quantity.
stock_already_held 409 A hold names stock that is already quarantined or damaged (its stockStatus, or the serials, are included). Release it, then hold it again to change the hold.
stock_not_held 409 A release names stock that isn’t held (its stockStatus, or the serials, are included).
pick_exceeds_allocation 409 A pick asks for more than its allocation line has left to pick (its unpickedQuantity, or the serials already picked, are included).
allocation_released 409 The allocation was released: it can’t be picked or released again.

The token and revocation endpoints, /connect/token and /connect/revoke, follow the OAuth 2.0 error format that OAuth clients expect, not problem details:

{
"error": "invalid_grant",
"error_description": "The email or password is incorrect."
}

When you contact support about an error, quote its correlationId. It is also in the response’s X-Correlation-Id header, and it identifies the request in jtWMS’s logs. See Correlation IDs.