Summary
routstr-core v0.4.3 (0.4.3+g7fd0cdf, ghcr.io/routstr/core:latest) fails to validate a Cashu V3 cashuA token from a Nutshell 0.20.0 mint with the error:
{
"error": {
"message": "CASHU token processing failed: no keyset with ID: 0049550c03fb517f",
"type": "cashu_error",
"code": 400
}
}
The mint is registered as the only allowed mint (CASHU_MINTS=https://mint.refreshpoolpro.com), the mint is healthy, the keyset 0049550c03fb517f is the active V1-format keyset published by the mint, and the proofs in the token reference exactly that keyset ID. Yet routstr reports it doesn't know the keyset.
Environment
- routstr-core: v0.4.3 (commit
g7fd0cdf), image ghcr.io/routstr/core:latest, fresh DB (no carryover state)
- Mint: Nutshell 0.20.0, public URL
https://mint.refreshpoolpro.com
- Mint backend: LNbits → LND v0.19.3-beta
- Token: V3 cashuA, 3 sats, two proofs, generated via Nutshell CLI 0.20.0 with
--legacy flag
Mint metadata
GET https://mint.refreshpoolpro.com/v1/info:
{
"name": "Refresh Pool Mint",
"pubkey": "022be1e90eac4014ec0dac3e93328d1ab665c0abf871bfe1a56f362fe2649c607c",
"version": "Nutshell/0.20.0",
"description": "Private Cashu mint on Lightning",
"urls": ["https://mint.refreshpoolpro.com"],
"nuts": ["NUT-07", "NUT-08", "NUT-09"]
}
GET https://mint.refreshpoolpro.com/v1/keysets:
{
"keysets": [
{
"id": "0049550c03fb517f",
"unit": "sat",
"active": true,
"input_fee_ppk": 100
}
]
}
GET https://mint.refreshpoolpro.com/v1/keys returns the active keyset with 64 denomination keys for 0049550c03fb517f.
Routstr config
CASHU_MINTS=https://mint.refreshpoolpro.com
GET http://routstr/v1/info correctly reports:
{
"mints": ["https://mint.refreshpoolpro.com"]
}
So the mint URL is registered. But the keyset is not.
Reproduction
- Configure routstr-core v0.4.3 with
CASHU_MINTS=https://mint.refreshpoolpro.com only.
- Mint a small V3 cashuA token from the same mint via any wallet that emits TokenV3 (Nutshell CLI
cashu send 3 --legacy).
- POST a chat completion request with the token in
X-Cashu header:
T='cashuAeyJ0b2tlbi...' # V3 cashuA token, 3 sats, mint=https://mint.refreshpoolpro.com
curl -sm30 -XPOST http://127.0.0.1:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-H "X-Cashu: $T" \
-d '{"model":"qwen3-32b","messages":[{"role":"user","content":"hi"}],"max_tokens":5}'
Observed
{
"error": {
"message": "CASHU token processing failed: no keyset with ID: 0049550c03fb517f",
"type": "cashu_error",
"code": 400
}
}
Token is not spent (proofs remain valid in the wallet — re-receivable).
Expected
routstr should fetch the keyset from the registered mint when it encounters an unknown keyset ID for an allowed mint URL. The mint's /v1/keys endpoint exposes the keyset for free, no auth needed. After fetching, proof validation should proceed normally.
Notable
- The keyset ID
0049550c03fb517f is 16 hex characters = V1 keyset format. Newer Cashu wallets may emit V2-format keyset IDs (66 hex chars from a 33-byte pubkey). routstr-core may have a parsing constraint that only handles V2 IDs, treating V1 IDs as unknown even though the mint reports them.
- Empty-proofs cashuA tokens (
{"proofs":[],"mint":"..."}) do pass through routstr cleanly and return Insufficient balance — meaning the mint URL is recognized at one layer but the keyset registration/lookup at the proof-validation layer fails.
- V4 cashuB tokens (the default emitted by cashu.me) fail at an even earlier layer with
"Invalid authentication token format", before the keyset check is reached. That may be a separate sub-bug; happy to file separately if useful.
History
This bug was first encountered on 2026-05-05 against routstr-core 0.4.0 with the same mint. v0.4.3's release notes (refund handling, x-cashu flow, multi-mint swaps, fee handling, model routing) did not appear to touch this code path. Re-verified today (2026-05-09) on a fresh deployment with wiped DB and the canonical ghcr.io/routstr/core:latest image — same error.
Workaround
None on the routstr side. Forced to fall back to L402 / Aperture / direct LND payment paths until this is fixed.
What would help me move forward
Either:
- Confirmation that V1 keyset IDs (16 hex chars) are intentionally unsupported, in which case operators with older Nutshell deployments need to know to upgrade keysets, OR
- A pointer to where keyset registration/lookup happens in the codebase so I can submit a fix for V1 ID handling.
Happy to provide additional logs, full token, or test directly against any patched build.
Summary
routstr-core v0.4.3 (
0.4.3+g7fd0cdf,ghcr.io/routstr/core:latest) fails to validate a Cashu V3 cashuA token from a Nutshell 0.20.0 mint with the error:The mint is registered as the only allowed mint (
CASHU_MINTS=https://mint.refreshpoolpro.com), the mint is healthy, the keyset0049550c03fb517fis the active V1-format keyset published by the mint, and the proofs in the token reference exactly that keyset ID. Yet routstr reports it doesn't know the keyset.Environment
g7fd0cdf), imageghcr.io/routstr/core:latest, fresh DB (no carryover state)https://mint.refreshpoolpro.com--legacyflagMint metadata
GET https://mint.refreshpoolpro.com/v1/info:{ "name": "Refresh Pool Mint", "pubkey": "022be1e90eac4014ec0dac3e93328d1ab665c0abf871bfe1a56f362fe2649c607c", "version": "Nutshell/0.20.0", "description": "Private Cashu mint on Lightning", "urls": ["https://mint.refreshpoolpro.com"], "nuts": ["NUT-07", "NUT-08", "NUT-09"] }GET https://mint.refreshpoolpro.com/v1/keysets:{ "keysets": [ { "id": "0049550c03fb517f", "unit": "sat", "active": true, "input_fee_ppk": 100 } ] }GET https://mint.refreshpoolpro.com/v1/keysreturns the active keyset with 64 denomination keys for0049550c03fb517f.Routstr config
GET http://routstr/v1/infocorrectly reports:{ "mints": ["https://mint.refreshpoolpro.com"] }So the mint URL is registered. But the keyset is not.
Reproduction
CASHU_MINTS=https://mint.refreshpoolpro.comonly.cashu send 3 --legacy).X-Cashuheader:Observed
{ "error": { "message": "CASHU token processing failed: no keyset with ID: 0049550c03fb517f", "type": "cashu_error", "code": 400 } }Token is not spent (proofs remain valid in the wallet — re-receivable).
Expected
routstr should fetch the keyset from the registered mint when it encounters an unknown keyset ID for an allowed mint URL. The mint's
/v1/keysendpoint exposes the keyset for free, no auth needed. After fetching, proof validation should proceed normally.Notable
0049550c03fb517fis 16 hex characters = V1 keyset format. Newer Cashu wallets may emit V2-format keyset IDs (66 hex chars from a 33-byte pubkey). routstr-core may have a parsing constraint that only handles V2 IDs, treating V1 IDs as unknown even though the mint reports them.{"proofs":[],"mint":"..."}) do pass through routstr cleanly and returnInsufficient balance— meaning the mint URL is recognized at one layer but the keyset registration/lookup at the proof-validation layer fails."Invalid authentication token format", before the keyset check is reached. That may be a separate sub-bug; happy to file separately if useful.History
This bug was first encountered on 2026-05-05 against routstr-core 0.4.0 with the same mint. v0.4.3's release notes (refund handling, x-cashu flow, multi-mint swaps, fee handling, model routing) did not appear to touch this code path. Re-verified today (2026-05-09) on a fresh deployment with wiped DB and the canonical
ghcr.io/routstr/core:latestimage — same error.Workaround
None on the routstr side. Forced to fall back to L402 / Aperture / direct LND payment paths until this is fixed.
What would help me move forward
Either:
Happy to provide additional logs, full token, or test directly against any patched build.