Skip to content

0.48.1 — the error says whether money moved, and the tool refuses a quote it was not told about (fixes #132) - #143

Open
VickyXAI wants to merge 11 commits into
mainfrom
fix/issue-132-not-charged-wording
Open

0.48.1 — the error says whether money moved, and the tool refuses a quote it was not told about (fixes #132)#143
VickyXAI wants to merge 11 commits into
mainfrom
fix/issue-132-not-charged-wording

Conversation

@VickyXAI

@VickyXAI VickyXAI commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Fixes #132.

Summary

The reporter saw API error after payment: 502 / Request failed on blockrun_markets sports/categories and a 502/501 on blockrun_price stocks, while the wallet balance never changed. The balance was right and the words were wrong, on three layers.

Errors (src/utils/errors.ts)

  • extractErrorMessage now reads the detail field that @blockrun/llm 3.15.1 (blockrun-llm-ts#39, merged and released this session) uses to carry the gateway's own message, e.g. Predexon 500: … (payment NOT charged). Our extractor only read message/hint, so the SDK fix alone would have changed nothing here.
  • A 501 is now "the gateway does not serve this endpoint", not "temporary API issue, try again". The "nothing was charged" claim is made only when the 501 arrived before payment.
  • hasLabelledServerStatus is exported so route-specific formatters share one status rule.

Markets (src/tools/markets.ts, src/utils/markets-validation.ts)

  • All four Predexon sports/* routes have returned an upstream 500 on every call since 2026-08-04 (re-verified live 2026-09-08). The gateway marks them degraded, withdrew them from discovery, and releases the payment nonce on upstream 5xx. The tool description now says so and points at markets + league=; a sports/* 5xx renders the outage, the date, and "nothing was charged". No pre-payment block: the gateway decides whether Predexon has recovered.

Price (src/tools/price.ts)

  • Since 2026-09-05 (blockrun#517) the gateway returns a pre-payment 501 for every stocks/{market}/price|history call. On the default Solana chain the Base-only guard fired first and told the user to switch chains to pay for a route that cannot succeed. Paid stock calls now return the gateway's own answer before the wallet is consulted: withdrawn on 2026-09-05, nothing charged, the ticker catalog is still free, and who to contact.

Quote guard (src/utils/budget.ts, src/tools/video.ts, src/tools/image.ts, src/utils/solana-402.ts) — found by npm run verify:prices while cutting this release

  • sol.blockrun.ai is a separate deployment that lags Base: it does not know azure/sora-2 and quotes "Seedance 2.0 Pro video generation (5s)" at $1.135480 in its place (Base: "Sora 2 video generation (4s)" at $0.421001). The only check on a 402 price was the budget cap, which pays that on any wallet holding $2.
  • assertQuoteNearEstimate refuses, unsigned, any quote more than 1.5x and $0.02 above the estimate the model was shown. Wired into blockrun_video on both rails and blockrun_image on Solana; the Solana helper now hands onQuote the decoded 402 so the message can name what the gateway labelled the quote. Every refusal ends "no charge was made".
  • scripts/verify-prices.ts classifies a differing product label with a materially dearer Solana price as a gateway bug (loud, exit 0) instead of an estimator gap; run 4 on 2026-09-08: 0 under-reserved, 1 substituted (Sora), 3 Anthropic chat rows dearer on Solana but covered by the reserve.

Merge — the branch was originally cut from 0.48.0 before #131/#140/#141 landed; origin/main is merged in (dbb8a44), so the PR no longer reverts them.

Docs

  • README, crypto-data, gentech-blockrun, prediction-markets, surf skills and the plugin manifest stop promising paid equity quotes and live sports routes. Context-cost profile table synced to the measured totals (12,992 full / 5,606 trading; badge unchanged at 13.0K).

Release

Live verification

In-process handler calls against the production gateway, after the change and with @blockrun/llm 3.15.1 installed:

blockrun_price {"action":"price","category":"stocks","market":"us","symbol":"AAPL"} (1ms)
Error: Equity quotes are not served (gateway 501 for category "stocks").
The gateway withdrew equity price and history on 2026-09-05 — this is not an outage, retrying will not help, and nothing was charged (the wallet was not asked to sign).
The ticker catalog still works and is free: { action: "list", category: "stocks", market: "us" }.

blockrun_markets {"path":"sports/categories"} (3098ms)
Error: API error after payment: 502
Request failed
Predexon's sports/* routes have returned an upstream 500 on every call since 2026-08-04. The gateway still routes them but no longer advertises them, and it releases the payment when upstream fails — nothing was charged for this call.

Test Coverage

New tests: detail is surfaced and deduplicated; pre-#39 shape unchanged; 501 pre-payment vs post-payment wording; "501 items" is not a status; sports path recognition incl. percent-encoded; sports 5xx vs 4xx vs non-sports; equity pre-flight text for stocks and usstock. The paid-stock row is retired from the spend-confirmation coverage table with a re-add note.

Tests: 462 → 488 (+26 new: 15 for #132, 8 for the quote guard, 3 from #140 via the merge).

Pre-Landing Review

/review ran on this change with two adversarial passes (fresh-context Claude subagent + Codex). 13 findings, all addressed; the two that mattered: a post-payment 501 must not claim "nothing was charged", and the sports matcher must use the same labelled-status rule as formatError.

Design Review

No frontend files changed — design review skipped.

Eval Results

No prompt-related files changed — evals skipped.

Scope Drift

Scope Check: CLEAN. Intent: fix #132's misleading wording and stop advertising routes the gateway does not serve. The three extra commits in the range were already on main.

Plan Completion

No plan file detected.

TODOS

No TODOS.md in this repo.

Documentation

Synced by the document-release pass (commit 5f5777c):

  • README.md: Troubleshooting gains two bullets for the bug: price and markets routes return 502 in live MCP calls #132 symptoms (equity 501: withdrawn 2026-09-05, nothing charged, action:"list" still free; sports/*: upstream 500 since 2026-08-04, payment released, older builds rendered it as API error after payment: 502). The cost-reporting table drops "paid blockrun_price" and states blockrun_image's account-rail cost as settled (fix(image): read the settled cost on the account rail instead of estimating #140).
  • skills/blockrun-debug/SKILL.md: three new symptom → cause → fix rows (equity 501, sports/* outage, generic 501 "not served") plus matching triggers.
  • Already in sync: tools table, context-cost table, crypto-data, gentech-blockrun, prediction-markets, surf, plugin manifest.

Documentation debt flagged, not fixed here: docs/mcp-schema-overhead.md is a self-dated 2026-09-01 snapshot whose profile table (12,900 / 5,554) now differs from the README's test-pinned figures; and the tracked VERSION file reads 0.41.1 while package.json is the version source.

Test plan

  • npm run typecheck clean
  • npm run build clean
  • npm test: 488 pass, 0 fail (recorded in the gstack evidence ledger)
  • npm run verify:prices: exit 0 — 0 under-reserved on either chain; the Sora/Solana substitution is reported as a gateway bug
  • Both error paths exercised live against the gateway (above); the sports call settled nothing

🤖 Generated with Claude Code

https://claude.ai/code/session_01RNqnahSKcBqQemPn5TaMLg

VickyXAI and others added 11 commits September 8, 2026 18:04
…ansient outage

@blockrun/llm 3.15.1 carries the gateway's own message — the field that names
the cause and says '(payment NOT charged)' — under `detail`. extractErrorMessage
only read message/hint, so the text was dropped a second time here and the
'not charged' branch never fired (#132).

A 501 is the gateway declining to serve a route, not a blip; the advice to
retry in a few minutes was wrong. The 'nothing was charged' claim is made only
when the 501 arrived before payment. hasLabelledServerStatus is exported so
route-specific formatters share one status rule.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNqnahSKcBqQemPn5TaMLg
…charged

All four Predexon sports/* routes have returned an upstream 500 since
2026-08-04. The gateway marks them degraded, withdrew them from discovery and
releases the payment nonce on upstream 5xx; this server still advertised them
as live and rendered the failure as 'after payment … try again' (#132).

The description now says the routes are degraded and points at markets +
league=. A sports 5xx renders the outage, the date and 'nothing was charged'.
No pre-payment block: the gateway decides whether Predexon has recovered.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNqnahSKcBqQemPn5TaMLg
Since 2026-09-05 the gateway returns a pre-payment 501 for every
stocks/{market}/price|history call — 'We do not currently serve equity
prices'. On the default Solana chain the Base-only guard fired first and told
the user to switch chains to pay for a route that cannot succeed (#132).

Paid stock calls now return the gateway's own answer up front: withdrawn on
2026-09-05, nothing charged, the ticker catalog is still free, contact for
coverage. The description stops promising equity quotes. The paid-tool
confirmation table drops the stock row with a note on how to re-add it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNqnahSKcBqQemPn5TaMLg
…-cost table

README, four skills and the plugin manifest still sold paid stock quotes and the
sports/* Predexon routes. Both now read as what the gateway serves. The
context-cost profile table is updated to the measured totals after the
description edits (12,992 full / 5,606 trading).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNqnahSKcBqQemPn5TaMLg
Bump @blockrun/llm to ^3.15.1 (the SDK half of #132) and package version to
0.48.1. Also ships the three fixes that landed on main after 0.48.0: image
account-rail settled cost (#140), OpenClaw verification and DeepSeek repricing
(#131), brand numbers (#141).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNqnahSKcBqQemPn5TaMLg
README troubleshooting and the blockrun-debug skill now carry the two
issue-132 symptoms as symptom → cause → fix: the equity 501 from
blockrun_price (withdrawn 2026-09-05, nothing charged, catalog still free)
and the sports/* upstream outage behind blockrun_markets (degraded since
2026-08-04, payment released; older builds rendered it as "API error after
payment: 502"). A third row covers the generic 501 "not served" wording and
when it can and cannot claim nothing was charged. The debug skill's
description and triggers pick up the new error strings.

The cost-reporting table drops "paid blockrun_price" — no paid price path
remains — and states blockrun_image's account-rail cost as settled (#140),
with the estimate only as the fallback when no figure is returned.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNqnahSKcBqQemPn5TaMLg
…gning

verify:prices found the Solana gateway — a separate deployment that can lag
Base — does not know azure/sora-2 and quotes 'Seedance 2.0 Pro video
generation (5s)' at $1.135480 in its place, 2.7x the published Sora rate for a
different model. The only check on the 402 price was the budget cap, which
lets that through on any wallet holding $2.

assertQuoteNearEstimate (budget.ts) refuses, unsigned, a quote more than 1.5x
and $0.02 above the estimate the model was shown. Wired into blockrun_video on
both rails and blockrun_image on Solana; the Solana helper now passes the
decoded 402 to onQuote so callers can name WHAT was quoted. Messages end with
'no charge was made' and say how to proceed (for Sora: switch to Base).

Two Solana tests that used a 4x quote to exercise the re-reserve now use a
1.27x quote — the 4x case is the thing being refused.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNqnahSKcBqQemPn5TaMLg
…, not an under-reserve

The 402 says what is being sold (Base under resource.description, Solana under
accepts[0].extra.description). When the two gateways name different products
for the same request, reserving the substitute's price would legitimise the
substitution; since the tools now refuse such a quote before signing, it is
reported loudly as a gateway bug and does not fail the release gate.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNqnahSKcBqQemPn5TaMLg
CHANGELOG paragraph for the refused-quote behaviour; a symptom → cause → fix
row in the debug skill; README profile totals resynced (13,023 full / 5,558
media). The full profile crossed 13,000 tokens, which rounds the badge's
share of a 200K window from 6% to 7%, so the card is regenerated.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNqnahSKcBqQemPn5TaMLg
…s also materially dearer

The Solana gateway writes longer descriptions for the same route (rpc/ethereum:
40 words against Base's 5, same $0.002), which the first cut read as a
substituted product. Substitution now requires the label to differ AND the
Solana price to sit >25% above Base; the per-row tag says whether the tool is
guarded (video/image) or merely reserves the Base figure.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNqnahSKcBqQemPn5TaMLg
@VickyXAI VickyXAI changed the title 0.48.1 — the error says whether money moved (fixes #132) 0.48.1 — the error says whether money moved, and the tool refuses a quote it was not told about (fixes #132) Sep 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: price and markets routes return 502 in live MCP calls

1 participant