Skip to main content
Start with the contract for the interface you call. Embedded Node errors, ResponseCX HTTP responses, and other engines expose different fields. An error handler needs both the failure code and the operation’s replay behavior to choose a useful next action.

Read the right error shape

The published Node binding unwraps native errors into JavaScript errors. details.httpStatus is metadata on an engine failure; a local call did not make an HTTP request. Argument-conversion errors can retain a native binding code instead. Do not assume every thrown value has a known commerce code, and do not parse an error message as a universal JSON response.

Turn an expected rejection into an actionable result

The example below handles one operation-specific failure: a manual stock reservation that cannot be satisfied. It returns an out-of-stock result for that case and propagates every other error. It never retries a reservation automatically. Use Node.js 20.20.0+, npm 10+, and @stateset/embedded 1.35.1:
Save this as error-handling.test.mjs:
Success: the runner reports 3 tests, 3 passed, 0 failed, and exits with status 0. The first two tests call the real engine. The third injects an unexpected error to verify that your handler preserves it and makes exactly one attempt. available is a fresh stock observation after the rejection, not a promise that those units will remain available. A later checkout must reserve again against current stock. If the stock lookup itself fails, that error propagates rather than inventing an availability value. This helper creates manual checkout holds. Do not add it around an order workflow that already reserves the same units; the orders quickstart demonstrates order-managed reservations.

Choose the next action by operation

These are examples from the customer, payment, and return walkthroughs. A code such as VALIDATION names a category; it does not identify every failed precondition.

Retry HTTP requests deliberately

Before retrying, establish all three:
  1. The failure is one the service describes as retryable, or a transient failure on a read.
  2. Repeating the operation is safe under that endpoint’s contract. A custom header does not make an endpoint idempotent if the server does not support it.
  3. The retry has a bound: an attempt limit and an overall deadline. Stop when either is reached.
For supported write replays, persist the original key and request before sending the first attempt. Reuse that same key and payload within the endpoint’s documented replay window. Keep any returned resource or operation ID for reconciliation. Changing the payload is an intentional new operation, not a retry of the old one. Use the service’s retry guidance, including Retry-After when supplied. Schedule a retry only if its delay fits the remaining deadline; otherwise surface the failure or defer the operation. For retryable failures without a prescribed delay, use bounded backoff with jitter to spread attempts across clients. Delaying a request does not make a non-replayable write safe.

A ResponseCX conflict is not automatically success

The agent creation contract distinguishes: Authentication failures need the correct host, header, credential, or scope. A delay does not fix a 401 or 403. Validation errors need a corrected request. Read the response code before classifying an HTTP status as a retry signal.

Reconcile uncertain outcomes

A timeout means the client did not receive a usable result. A write may still have completed. The same caution applies to a gateway error after a downstream service accepted an operation. For a supported replay, resend the original operation according to that endpoint’s contract. Otherwise, use its returned operation ID or documented lookup to inspect the outcome. If you cannot establish whether it completed, retain an unresolved state for reconciliation instead of issuing another write with a new identity. Apply this separately to each system. A local payment idempotency key does not configure a provider’s retry behavior. A payment timeout also does not establish that you should release a stock hold: reconcile the payment before deciding what the inventory workflow should do.

Capture useful failure context

Record the interface and version, operation name, attempt number, elapsed time, error code, and any request/correlation ID the service supplies. Preserve the original exception as the cause when adding context. A database path or workspace mismatch can matter as much as the request body. Use a redacted diagnostic message rather than logging credentials, entire customer records, or unrestricted response bodies. There is no universal error.request_id field across the engines; the error-envelope table shows the service-specific locations. The support checklist lists the information needed for a reproduction.

Next steps

Last modified on September 20, 2026