unexpected_state API Origin: Application & API Last updated 13 Oct 2026

API Error: Invalid state transition — operation not allowed in the resource’s current state

The request is valid, but the object is in a state where this action isn’t allowed — cancelling something already completed, refunding an unpaid charge, shipping a cancelled order.

Exact message you may see invalid state transitioncannot be canceled becauseis not in a valid statebusiness rule violation
Seen on: REST API

Meaning

Business objects have life cycles (draft → open → paid → refunded) and each action is only legal from certain states. APIs reject illegal moves with 400/409/422 and codes like Stripe’s payment_intent_unexpected_state, invalid_state_transition or “cannot be X because it is Y”.

It often follows a race: a webhook or another user already moved the object on, so the client’s view is stale. Business-rule failures such as “amount exceeds available balance” are reported the same way.

Common causes

  • Object already in a final state (completed, cancelled, refunded)
  • Required earlier step not done yet (not confirmed, not paid)
  • Stale local state — a webhook/other process already changed it
  • Business rule violated (amount above balance, limit reached)

⚡ Quick fix

  1. Fetch the object and check its current status before acting
  2. Perform the missing earlier step first
  3. Treat “already done” as success where that’s the intended outcome

Detailed fix by platform

Node.js

  1. javascript
    const pi = await stripe.paymentIntents.retrieve(id);
    if (['requires_payment_method', 'requires_confirmation', 'requires_action', 'processing', 'requires_capture'].includes(pi.status)) await stripe.paymentIntents.cancel(id);

How to diagnose

  1. Status — Current state of the object right now
  2. Transitions — Which states allow this action (docs)?
  3. Events — Did a webhook/other actor change it?

🔧 Still not fixed?

Many errors look alike. If the steps above didn’t solve it, one of these is probably what you’re facing:

Where this error sits

Origin: Application & API. Errors that are often confused with or caused by this one (click to open):

409 — HTTP 409 Conflict (HTTP)409422 — HTTP 422 Unprocessable Content (HTTP)422423 — HTTP 423 Locked (HTTP)423Actions must be plain objects — Error: Actions must be plain objects. Instead, the actual type was: 'function'. (React)Actions must be plain…ALREADY_EXISTS — API Error: Resource already exists (ALREADY_EXISTS / resource_already_exists / 409) (API)ALREADY_EXISTSError acquiring the state lock — Terraform: Error: Error acquiring the state lock — ConditionalCheckFailedException / state blob is already locked (Terraform)Error acquiring the s…IllegalStateException — java.lang.IllegalStateException (Java)IllegalStateExceptionMaximum update depth — Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. (React)Maximum update depthunexpecte…

Explore the map of this error Full error map →

🧠 Still stuck? Analyze your error

Paste the full message, response headers or stack trace — we'll detect the platform and point to the most likely cause.

💬 What worked for others

No tips yet — did something else fix this for you?

Share what worked for you

Tips are checked by an editor before they appear. Links are removed.