You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
sum_of_matched_orders server-side counter accumulates without decrementing — phantom balance lock after ~10–20 FAK fills
Variant of #287. All client-side workarounds tested in #287 are confirmed
ineffective on my wallet. Posting fresh evidence so a maintainer can manually
reset the counter (and so the underlying CLOB cache bug stays visible).
TL;DR
After ~10–20 FAK BUY orders that fill instantly (status=matched), the CLOB
starts rejecting every new order with not enough balance / allowance, even
though:
on-chain pUSD balance is correct,
on-chain allowances to all 3 V2 spenders are MAX,
GET /balance-allowance returns the correct balance and MAX allowances,
get_trades() shows the recent fills as CONFIRMED (zero pending),
update_balance_allowance(COLLATERAL) has no effect,
this is not the V2 migration issue (USDC.e fully wrapped to pUSD),
The CLOB error message itself shows the cause: sum of matched orders keeps
growing as I trade and never decrements after on-chain settlement, until it
eats up the entire balance.
Markets: high-frequency hourly crypto markets (lots of small fast trades)
Order type: FAK BUY (limit at top of book, fills instantly → status=matched)
The error
PolyApiException[status_code=400, error_message={
'error': 'not enough balance / allowance: the balance is not enough -> '
'balance: 451837636, '
'sum of matched orders: 450825840, '
'order amount (inc. fees): 2969720'
}]
After this error fires, every subsequent order is rejected the same way
until enough time passes (sometimes 10+ minutes, sometimes longer).
Restarting the client / rotating API keys / re-approving on-chain does not
help.
What I verified before posting (please don't close as user error)
CLOB sees the same balance as the chain ($570.94), and the same MAX
allowances. Side-by-side test on signature_type=2 returns balance=0, allowances=0 (the bucket I'm not using), so this also rules out:
3. Trades are settled — sum_of_matched_orders is stale
get_trades() over the last 300 trades:
status
count
CONFIRMED
300
MINED
0
MATCHED
0
RETRYING
0
FAILED
0
There are zero unsettled trades. There is nothing on-chain that should
correspond to a sum_of_matched_orders of $450.
4. Probing the counter directly
I built a small probe that intentionally submits an unfillable BUY at price=0.01, size=N to trigger the balance check error and parse it. With probe_usd=$600 while in the stuck state, CLOB returns:
balance: $451.84
sum of matched orders: $450.83
sum of active orders: $0.00 (no resting orders)
order amount: $2.97 — $617 (varies with probe size)
=> available = $1.01
So:
the CLOB cached "balance" is even lower than the on-chain pUSD balance
($451.84 vs $570.94 on-chain — already $119 of drift in the wrong direction),
the CLOB sum_of_matched_orders cache has $450.83 sitting in it
even though get_trades says everything is CONFIRMED.
The available pool the matcher actually checks against is therefore ~$1
instead of the real ~$570.
Reproduction (consistent across days)
Start with a freshly funded proxy wallet, on-chain state perfect, CLOB
balance/allowance perfect.
Submit ~10–20 FAK BUYs on hourly crypto markets that match instantly
(status=matched, total notional $50–100).
Within a minute or two, the next BUY (any size, any market) is rejected
with not enough balance / allowance and the error reveals sum of matched orders ~ wallet balance, even though all earlier trades
are CONFIRMED on-chain.
The counter does not drain on its own within several minutes.
Submitting a passive GTC limit BUY that rests on the book (status=live)
does not make the counter grow. Only status=matched fills do.
This matches the pattern jmsaavedra called out in #287:
Every buy that returns status=matched (instant fill) breaks 100% sells.
Every buy that goes to status=live first (rests on book, fills later)
allows normal sells at any size.
…except the symptom on my side hits the BUY path (collateral side),
not just the sell path (shares side).
What I tried that did NOT work
Attempt
Result
update_balance_allowance(COLLATERAL) once
❌ no change
update_balance_allowance(COLLATERAL) in a loop
❌ no change
Re-derive API key + recreate ClobClient
❌ no change
Cancel all open orders + reconcile orphans
❌ I have zero open orders, no orphans
Wait 1, 5, 10 minutes
❌ counter persists
On-chain re-approve pUSD to all 3 V2 spenders
❌ counter persists (and allowances were already MAX)
Reduce probe order amount to $1
❌ still rejected — available is roughly $1
The only way I've been able to "unstick" the wallet is:
wait a long time (sometimes >30 min) and hope it drains, or
switch to a completely different funder wallet (counter is per-wallet, so a
fresh wallet has a clean counter — until it accumulates the same way).
What I'm asking for
Manual counter reset for the affected funder so I can keep using it
(DM-able privately, not posting the address publicly).
Confirmation that the bug is reproducing on your side and is being looked
at — even an acknowledgement would help users stop chasing
already-disproved client-side fixes (V2 migration, sigType-flip, fresh
approvals, fresh API keys, etc.).
Ideally: have the matcher decrement sum_of_matched_orders once the
corresponding on-chain trade reaches CONFIRMED. Right now it accumulates
monotonically per (funder, asset).
Anonymized minimal repro script
This is the same probe I ran above; it parses the CLOB error to expose the
hidden counter. Happy to share the full script if useful.
frompy_clob_client_v2import (
ApiCreds, ClobClient, OrderArgs, OrderType, PartialCreateOrderOptions,
)
frompy_clob_client_v2.order_builder.constantsimportBUYc=ClobClient(host="https://clob.polymarket.com", chain_id=137,
key=PRIVATE_KEY, funder=FUNDER, signature_type=1)
creds=c.create_or_derive_api_key()
c.set_api_creds(ApiCreds(creds.api_key, creds.api_secret, creds.api_passphrase))
# unfillable probe: well below any sane bid, large enough to exceed availableorder=c.create_order(
OrderArgs(token_id=TOKEN_ID, price=0.01, size=600/0.01, side=BUY),
PartialCreateOrderOptions(neg_risk=False),
)
try:
c.post_order(order, OrderType.GTC)
exceptExceptionase:
print(e) # <-- 'balance: A, sum of matched orders: B, order amount: C'
If B (sum of matched orders) is non-zero while get_trades() shows zero
non-confirmed trades, the counter is stuck.
TL;DR for maintainers: the matcher's per-funder sum_of_matched_orders cache does not decrement after the corresponding
trade reaches CONFIRMED on-chain. Same root cause as #287; client-side
mitigations from that thread (including lazymac2x's "wrap to pUSD" fix and
Hyperflex PR #50's sigType-flip retry) have been verified inapplicable to
this configuration. Need a server-side fix or per-funder counter reset.
sum_of_matched_ordersserver-side counter accumulates without decrementing — phantom balance lock after ~10–20 FAK fillsTL;DR
After ~10–20 FAK BUY orders that fill instantly (
status=matched), the CLOBstarts rejecting every new order with
not enough balance / allowance, eventhough:
GET /balance-allowancereturns the correct balance and MAX allowances,get_trades()shows the recent fills asCONFIRMED(zero pending),update_balance_allowance(COLLATERAL)has no effect,The CLOB error message itself shows the cause:
sum of matched orderskeepsgrowing as I trade and never decrements after on-chain settlement, until it
eats up the entire balance.
Environment
py-clob-client-v2(latest)signature_type=1(POLY_PROXY)status=matched)The error
After this error fires, every subsequent order is rejected the same way
until enough time passes (sometimes 10+ minutes, sometimes longer).
Restarting the client / rotating API keys / re-approving on-chain does not
help.
What I verified before posting (please don't close as user error)
1. On-chain state — perfect
So this rules out:
USDC.e residual, the wrap step is already done, and all three v2-spender
pUSD approvals are MAX. The fix does not apply.
2. CLOB
/balance-allowance— also perfectGET /balance-allowance?asset_type=COLLATERALwithsignature_type=1:{ "balance": "570937117", "allowances": { "0xE111180000d2663C0091e4f400237545B87B996B": "115792089237316195423570985008687907853269984665640564039457584007913129639935", "0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296": "115792089237316195423570985008687907853269984665640564039457584007913129639935", "0xe2222d279d744050d28e00520010520000310F59": "115792089237316195423570985008687907853269984665640564039457584007913129639935" } }CLOB sees the same balance as the chain ($570.94), and the same MAX
allowances. Side-by-side test on
signature_type=2returnsbalance=0, allowances=0(the bucket I'm not using), so this also rules out:indexed under sigType=1; they are not split across sigType buckets. The
Hyperflex PR Remove ApiCreds Logging #50 sigType-flip workaround is not applicable to my case
(and was reverted upstream anyway in PR Bump Version to 0.2.2 #51 because flipping to sigType=1
on Safe wallets fails sig recovery — different failure mode entirely).
3. Trades are settled —
sum_of_matched_ordersis staleget_trades()over the last 300 trades:There are zero unsettled trades. There is nothing on-chain that should
correspond to a
sum_of_matched_ordersof $450.4. Probing the counter directly
I built a small probe that intentionally submits an unfillable BUY at
price=0.01, size=Nto trigger the balance check error and parse it. Withprobe_usd=$600while in the stuck state, CLOB returns:So:
($451.84 vs $570.94 on-chain — already $119 of drift in the wrong direction),
sum_of_matched_orderscache has $450.83 sitting in iteven though
get_tradessays everything isCONFIRMED.The available pool the matcher actually checks against is therefore ~$1
instead of the real ~$570.
Reproduction (consistent across days)
balance/allowance perfect.
(
status=matched, total notional $50–100).with
not enough balance / allowanceand the error revealssum of matched orders~ wallet balance, even though all earlier tradesare
CONFIRMEDon-chain.status=live)does not make the counter grow. Only
status=matchedfills do.This matches the pattern jmsaavedra called out in #287:
…except the symptom on my side hits the BUY path (collateral side),
not just the sell path (shares side).
What I tried that did NOT work
update_balance_allowance(COLLATERAL)onceupdate_balance_allowance(COLLATERAL)in a loopClobClientavailableis roughly $1The only way I've been able to "unstick" the wallet is:
fresh wallet has a clean counter — until it accumulates the same way).
What I'm asking for
(DM-able privately, not posting the address publicly).
at — even an acknowledgement would help users stop chasing
already-disproved client-side fixes (V2 migration, sigType-flip, fresh
approvals, fresh API keys, etc.).
sum_of_matched_ordersonce thecorresponding on-chain trade reaches
CONFIRMED. Right now it accumulatesmonotonically per (funder, asset).
Anonymized minimal repro script
This is the same probe I ran above; it parses the CLOB error to expose the
hidden counter. Happy to share the full script if useful.
If
B(sum of matched orders) is non-zero whileget_trades()shows zeronon-confirmed trades, the counter is stuck.
TL;DR for maintainers: the matcher's per-funder
sum_of_matched_orderscache does not decrement after the correspondingtrade reaches
CONFIRMEDon-chain. Same root cause as #287; client-sidemitigations from that thread (including lazymac2x's "wrap to pUSD" fix and
Hyperflex PR #50's sigType-flip retry) have been verified inapplicable to
this configuration. Need a server-side fix or per-funder counter reset.