Uh oh!
There was an error while loading. Please reload this page.
Add missing OutgoingTransactionFailureReason enum values - #629
Conversation
Add EXECUTION_FAILED_POST_DEBIT, SETTLEMENT_FAILED, TIMEOUT, and MANUAL_REFUND to the OutgoingTransactionFailureReason enum so the public Grid API can represent the full set of failure reasons the backend emits. Without them, sparkcore's mapping from the internal UmaaasSendOperationFailureReason to this public enum (by name) throws a KeyError and reports an empty failure reason for settlement/timeout/manual-refund/post-debit failures.
akanter
commented
Jun 29, 2026
✱ Stainless preview builds for gridThis PR will update the cli go kotlin openapi php python ruby typescript ✅ grid-rubystudio · code
|
Greptile SummaryAdds four missing
Confidence Score: 5/5Safe to merge — a minimal, additive enum extension with no breaking changes and both bundled outputs correctly regenerated. The change is purely additive (new enum values only), the source file is the only hand-edited file, both bundles were regenerated via No files require special attention.
|
| Filename | Overview |
|---|---|
| openapi/components/schemas/transactions/OutgoingTransactionFailureReason.yaml | Source enum extended with four new values; this is the only hand-edited file in the PR and the change is correct |
| openapi.yaml | Regenerated bundle (via make build); diff is exactly the four added enum lines, consistent with the source change |
| mintlify/openapi.yaml | Second regenerated bundle for Mintlify docs; identical diff to openapi.yaml, as expected |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[sparkcore internal\nUmaaasSendOperationFailureReason] -->|name-based mapping| B{Key in public\nGridOutgoingTransactionFailureReason?}
B -->|Before this PR\nEXECUTION_FAILED_POST_DEBIT\nSETTLEMENT_FAILED\nTIMEOUT\nMANUAL_REFUND| C[KeyError → None\nblank failure reason]
B -->|After this PR\nall four values added| D[Correct enum value\nreturned to API consumer]
B -->|LSP_OPERATIONAL_FAILURE\nintentionally omitted| E[Maps to\nQUOTE_EXECUTION_FAILED]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[sparkcore internal\nUmaaasSendOperationFailureReason] -->|name-based mapping| B{Key in public\nGridOutgoingTransactionFailureReason?}
B -->|Before this PR\nEXECUTION_FAILED_POST_DEBIT\nSETTLEMENT_FAILED\nTIMEOUT\nMANUAL_REFUND| C[KeyError → None\nblank failure reason]
B -->|After this PR\nall four values added| D[Correct enum value\nreturned to API consumer]
B -->|LSP_OPERATIONAL_FAILURE\nintentionally omitted| E[Maps to\nQUOTE_EXECUTION_FAILED]
Reviews (1): Last reviewed commit: "Add missing OutgoingTransactionFailureRe..." | Re-trigger Greptile
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📌 Bolt Status 2026-07-17 17:05:45 UTC — ⚡ Agent |
Preview deployment for your docs. Learn more about Mintlify Previews.
|
Both sides extended OutgoingTransactionFailureReason additively: main added SCA_NOT_COMPLETED (#762), this branch adds EXECUTION_FAILED_POST_DEBIT, SETTLEMENT_FAILED, TIMEOUT and MANUAL_REFUND. Resolved as the union and regenerated both bundles with `make build`. Co-Authored-By: peterrojs <peterrojs@users.noreply.github.com>
Merged What conflicted: both sides extended How it was resolved: unioned the enum ( Verified:
One thing I can't clear myself: this repo's ruleset has One judgement call worth flagging: I deliberately kept the diff to exactly what was already approved. I did not add per-value description prose for the four new values, even though |
Merge activity
|
Uh oh!
There was an error while loading. Please reload this page.
sparkcore maps LSP_OPERATIONAL_FAILURE onto QUOTE_EXECUTION_FAILED — the distinction exists only for internal LSP-liquidity alerting, so the value never reaches an integrator. #629 made this call when it added the other missing enum members; this branch reintroduced it by mistake. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Removes EXECUTION_FAILED_POST_DEBIT, SETTLEMENT_FAILED, TIMEOUT and MANUAL_REFUND, added by #629 to mirror sparkcore's internal UmaaasSendOperationFailureReason. They are internal distinctions, not outcomes an integrator acts on differently: - EXECUTION_FAILED_POST_DEBIT exists so the compensation scanner knows a debit happened, and SETTLEMENT_FAILED is an internal leg failure. Both collapse into QUOTE_EXECUTION_FAILED, whose description now covers any internal failure on the way to settlement. - TIMEOUT and MANUAL_REFUND are SoFi-specific ops-initiated refunds. The outcome already surfaces on the refund object, whose reason enum carries TIMEOUT and USER_CANCELLATION. LIGHTNING_PAYMENT_FAILED's deprecation note now points at QUOTE_EXECUTION_FAILED rather than the removed SETTLEMENT_FAILED. BREAKING CHANGE: four values are removed from OutgoingTransactionFailureReason. sparkcore maps its internal enum onto this one by name, so it needs explicit mapping for these four before the vendored client is regenerated — otherwise the mapping KeyErrors and failureReason renders empty (the bug #629 fixed). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Removes three of the four values #629 added to mirror sparkcore's internal UmaaasSendOperationFailureReason. They are internal distinctions, not outcomes an integrator acts on differently: - SETTLEMENT_FAILED is an internal leg failure with no distinct integrator action, so it collapses into QUOTE_EXECUTION_FAILED. - TIMEOUT and MANUAL_REFUND are SoFi-specific ops-initiated refunds. The outcome already surfaces on the refund object, whose reason enum carries TIMEOUT and USER_CANCELLATION. EXECUTION_FAILED_POST_DEBIT is kept: pre-debit versus post-debit is exactly what tells an integrator whether to expect a refund. LIGHTNING_PAYMENT_FAILED's deprecation note now points at QUOTE_EXECUTION_FAILED rather than the removed SETTLEMENT_FAILED. BREAKING CHANGE: three values are removed from OutgoingTransactionFailureReason. sparkcore maps its internal enum onto this one by name, so it needs explicit mapping for these three before the vendored client is regenerated — otherwise the mapping KeyErrors and failureReason renders empty (the bug #629 fixed). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Removes the four values #629 added to mirror sparkcore's internal UmaaasSendOperationFailureReason. They are internal distinctions, not outcomes an integrator acts on differently: - EXECUTION_FAILED_POST_DEBIT exists so the compensation scanner knows a debit happened, and SETTLEMENT_FAILED is an internal leg failure. Both collapse into QUOTE_EXECUTION_FAILED, whose description now covers any internal failure on the way to settlement and states that a debited amount is refunded automatically. - TIMEOUT and MANUAL_REFUND are SoFi-specific ops-initiated refunds. The outcome already surfaces on the refund object, whose reason enum carries TIMEOUT and USER_CANCELLATION. LIGHTNING_PAYMENT_FAILED's deprecation note now points at QUOTE_EXECUTION_FAILED rather than the removed SETTLEMENT_FAILED. BREAKING CHANGE: four values are removed from OutgoingTransactionFailureReason. sparkcore maps its internal enum onto this one by name, so it needs explicit mapping for these four before the vendored client is regenerated — otherwise the mapping KeyErrors and failureReason renders empty (the bug #629 fixed). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The value is never returned. An operational failure on the provider side reaches integrators as QUOTE_EXECUTION_FAILED, which is the same outcome to act on, so the finer distinction has no public meaning. #629 made this call when it added the other missing enum members; this branch reintroduced it by mistake. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Removes the four values #629 added. Each describes an internal step of how a payment is processed rather than an outcome an integrator acts on differently: - EXECUTION_FAILED_POST_DEBIT and SETTLEMENT_FAILED say where on the way to settlement the failure happened. Both collapse into QUOTE_EXECUTION_FAILED, whose description now covers that whole path and states that a debited amount is refunded automatically. - TIMEOUT and MANUAL_REFUND describe operator-initiated refunds. That outcome already surfaces on the refund object, whose reason enum carries TIMEOUT and USER_CANCELLATION. LIGHTNING_PAYMENT_FAILED's deprecation note now points at QUOTE_EXECUTION_FAILED rather than the removed SETTLEMENT_FAILED. BREAKING CHANGE: four values are removed from OutgoingTransactionFailureReason. The server-side mapping for them has to be updated before clients are regenerated, or failureReason renders empty — see #629. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ly ones (#689) ## Summary Reworks `OutgoingTransactionFailureReason` so every value is an outcome an integrator acts on, and syncs the docs to match. **Added** — granular payout failures, set at the payout-partner boundary: - `PAYOUT_RETURNED` — receiving bank accepted then returned/reversed the payout - `LIMIT_EXCEEDED` — payout exceeds a recipient-, account-, or corridor-level limit - `ACCOUNT_CANNOT_RECEIVE` — account exists but can't accept the payment (dormant/frozen/restricted/unsupported currency) - `ACCOUNT_INVALID` — recipient account not found or details wrong - `COMPLIANCE_REJECTED` — rejected on compliance grounds (sanctions/watchlist/KYC-AML) **Removed** — the four values #629 added. Each names an internal step of how a payment is processed rather than something an integrator handles differently: - `EXECUTION_FAILED_POST_DEBIT` and `SETTLEMENT_FAILED` say where on the way to settlement the failure happened. Both collapse into `QUOTE_EXECUTION_FAILED`, whose description now covers that whole path and states that a debited amount is refunded automatically. - `TIMEOUT` and `MANUAL_REFUND` describe operator-initiated refunds. That outcome already surfaces on the refund object, whose `reason` enum carries `TIMEOUT` and `USER_CANCELLATION`. `LSP_OPERATIONAL_FAILURE` was on this branch earlier and is removed for the same reason: an operational failure on the provider side reaches integrators as `QUOTE_EXECUTION_FAILED`, the same outcome to act on. **Deprecated** in the description, still returned: `LIGHTNING_PAYMENT_FAILED` (superseded by `QUOTE_EXECUTION_FAILED`) and `COUNTERPARTY_POST_TX_FAILED` (coarse fallback for historical rows). `SCA_NOT_COMPLETED` (#762) is untouched — a customer letting an SCA challenge expire is a distinct, actionable outcome. Final enum: `QUOTE_EXPIRED`, `QUOTE_EXECUTION_FAILED`, `FUNDING_AMOUNT_MISMATCH`, `SCA_NOT_COMPLETED`, `PAYOUT_RETURNED`, `LIMIT_EXCEEDED`, `ACCOUNT_CANNOT_RECEIVE`, `ACCOUNT_INVALID`, `COMPLIANCE_REJECTED`, `LIGHTNING_PAYMENT_FAILED`, `COUNTERPARTY_POST_TX_FAILED`. ## Breaking change Removing four values is flagged by oasdiff as `request-property-enum-value-removed` (ERR), because `failureReason` also appears in the `webhook:outgoing-payment` and `webhook:agent-action` bodies. The PR carries the `breaking-change` label and needs API-reviewer approval. The server-side mapping for the removed values has to be updated before clients are regenerated, or `failureReason` renders empty — the regression #629 was fixing. ## Changes - **OpenAPI** (`OutgoingTransactionFailureReason.yaml` + bundle): the enum above, with per-value descriptions and deprecation notes. - **Docs**: synced the failure-reasons table in `transaction-lifecycle.mdx` and the list in the `error-handling.mdx` snippet to the enum — dropped the non-existent `INSUFFICIENT_BALANCE`, reordered to enum order, and fixed a `FAILED` webhook example to use `ACCOUNT_INVALID`. Rebased onto main, which added #629's values and #762's `SCA_NOT_COMPLETED`. ## Test plan - `make build` — bundles cleanly; clean rebuild produces no diff - `make lint-openapi` — 0 errors (redocly + spectral) --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com>

Summary
Adds four missing values to the public
OutgoingTransactionFailureReasonenum so the Grid API can represent the full set of failure reasons the backend actually emits:EXECUTION_FAILED_POST_DEBITSETTLEMENT_FAILEDTIMEOUTMANUAL_REFUNDWhy
sparkcore maps its internal
UmaaasSendOperationFailureReasononto this public enum by name (sparkcore/grid/objects/transaction.py::_get_outgoing_transaction_failure_reason). The internal enum has these four members but the public enum didn't, so the mapping threw a (caught)KeyError, logged"Key does not exist in GridOutgoingTransactionFailureReason", and returnedNone— meaning the API reported an empty failure reason for settlement / timeout / manual-refund / post-debit failures, plus noisy ERROR logs on every render of such a transaction.Surfaced while debugging the embedded-USDB onramp failures (those failed send-operations carry
SETTLEMENT_FAILED).What changed
openapi/components/schemas/transactions/OutgoingTransactionFailureReason.yaml— source enum (the only hand edit)openapi.yaml+mintlify/openapi.yaml— regenerated viamake build(redocly bundle)Notes / decisions
LSP_OPERATIONAL_FAILUREintentionally NOT added — sparkcore deliberately maps it toQUOTE_EXECUTION_FAILED(internal-only distinction for LSP-liquidity alerting), so it should never reach the public enum.EXECUTION_FAILED_POST_DEBIT: it's documented internally as an internal-only distinction (lets the compensation scanner safely credit). I chose to expose it for completeness so the mapping needs no special-case, but it could instead be mapped toQUOTE_EXECUTION_FAILEDin sparkcore likeLSP_OPERATIONAL_FAILURE. Easy to flip — happy to if you'd prefer to keep it internal.Follow-up (separate PR, needed for the runtime fix)
This is the canonical spec change. webdev's vendored generated
grid-apipython package (webdev/grid-api, consumed by sparkcore as a path dep) must be regenerated from this spec viagrid-api/update_schema.sh+ apackageVersionbump +sparkcore/uv.lockupdate for sparkcore to actually pick up the new members. That regen needs the Java/Maven/openapi-generator toolchain and is a separate webdev PR — until it lands, sparkcore stillKeyErrors.Test plan
make lint-openapi(redocly + spectral,--fail-severity=error) passes — no new findings🤖 cryptic-tempest(#1) | Feedback
Original PR: #628