Active bugs in py_clob_client v0.34.6 are causing silent failures, incorrect fee attribution, and stuck positions for developers building on Polymarket. This post documents every open GitHub issue that affects create_order(), post_order(), and sell flows — with reproduction code, workarounds, and the error messages you will actually see in your logs.
Why This Matters Now
Polymarket’s March 30 taker fee rollout changed the economics of every order. The SDK now auto-injects feeRateBps into signed order payloads, and fee-enabled markets reject orders without it. This interacts with several pre-existing bugs in ways that make debugging harder — a not enough balance / allowance error might be a balance issue, an allowance issue, a fee calculation issue, or a CLOB backend desync. Knowing which bugs are real and which are your code saves hours.
The issues below are all open on Polymarket/py-clob-client as of April 4, 2026. The SDK has 56 open pull requests and no new PyPI release since v0.34.6 on February 19, 2026.
Issue #301 — Minimum Order Size Validation Errors
Opened: March 16, 2026 by fkaragons
Status: Open
Affects: create_order(), post_order()
Small orders that should be valid based on the market’s minimum share size are rejected. The SDK’s client-side validation applies incorrect minimum thresholds before the order even reaches the CLOB API.
Error you will see:
Exception: size (X) lower than the minimum: Y
This error is raised inside client.py before the order is signed or posted. The minimum is determined per-market, but the SDK may cache or compute the wrong value.
Workaround: Check the market’s actual minimum order size via the Gamma API and validate manually before calling create_order():
import requests
def get_min_order_size(slug):
resp = requests.get(f"https://gamma-api.polymarket.com/markets?slug={slug}")
market = resp.json()[0]
return float(market.get("minimum_order_size", "1"))
min_size = get_min_order_size("bitcoin-above-100k")
if your_size >= min_size:
signed = client.create_order(order_args)
Related: This is distinct from issue #265 (below), where the minimum size error triggers specifically when selling fractional positions after fees.
Issue #294 — Reversed Maker/Taker Semantics on Sell Orders
Opened: March 9, 2026 by 198085919993s-rgb
Status: Open
Affects: post_order(), get_trades(), fee attribution
When placing sell orders, the trader_side field in the trade response may show MAKER when the order was actually a taker (or vice versa). This affects any agent logic that tracks maker vs. taker fills for fee accounting, rebate tracking, or P&L calculation.
Why it matters now: With taker fees active on nearly every market category since March 30, the maker/taker distinction directly affects your cost basis. Makers pay zero fees and earn rebates (20–50% by category). Takers pay fees up to 1.80%. If your agent logs the wrong side, your P&L is wrong.
What to check in your code:
trades = client.get_trades()
for trade in trades:
# trader_side may be incorrect on sell orders
reported_side = trade.get("trader_side") # "MAKER" or "TAKER"
fee_rate = trade.get("fee_rate_bps")
# Workaround: cross-reference with your order type
# If you posted with post_only=True and it filled, you ARE the maker
# If you posted with OrderType.FOK, you ARE the taker
print(f"Reported: {reported_side}, Fee BPS: {fee_rate}")
Workaround: Do not rely on trader_side from the API for sell orders. Instead, infer maker/taker status from your own order parameters: post_only=True means maker, OrderType.FOK means taker, and OrderType.GTC without post_only could be either (check if the order rested on the book or filled immediately).
Issue #293 — CLOB API Trades Not Appearing in Polymarket UI
Opened: March 2026
Status: Open
Affects: post_order(), position visibility
Orders placed via post_order() execute successfully — the API returns an orderID and the trade confirms — but the position does not appear in the Polymarket web UI. The on-chain state is correct (you hold the conditional tokens), but the UI’s backend doesn’t reflect the trade.
This issue is related to wallet type and address mapping. The Polymarket UI maps positions to your proxy wallet address. If there is a mismatch between the signing address your bot uses and the proxy address the UI expects, the trade is invisible in the UI even though it is real on-chain.
How to confirm your trade actually executed:
# Check via API — if this returns your position, the trade is real
positions = client.get_positions()
for pos in positions:
print(f"Token: {pos['asset']['token_id']}")
print(f"Size: {pos['size']}")
# Check via Data API — independent confirmation
import requests
address = "YOUR_PROXY_ADDRESS"
resp = requests.get(f"https://data-api.polymarket.com/positions?user={address}")
data = resp.json()
for p in data:
print(f"{p['title']}: {p['size']} shares")
Workaround: Ensure the address you pass as funder in ClobClient() matches the address shown on your Polymarket profile page. If you are using signature_type=1 (Magic/email wallet), the funder must be your Polymarket proxy address, not your signing key’s address. See issue #235 for the same root cause affecting balance display.
Issue #287 — Intermittent not enough balance / allowance Despite Verified Funds
Opened: February 28, 2026 by Moosetools
Status: Open
Affects: post_order(), all order types
Version: v0.34.6
This is the most reported bug in the repository. Orders fail with PolyApiException[status_code=400, error_message={'error': 'not enough balance / allowance'}] even when the wallet has verified USDC.e balance and MAX_UINT256 CTF Exchange allowance on-chain. The reporter had $222.45 USDC.e, 42 confirmed trades from prior sessions, and all API endpoints accessible — but every order placement failed.
The exact error:
py_clob_client.exceptions.PolyApiException: PolyApiException[status_code=400, error_message={'error': 'not enough balance / allowance'}]
Key details from the report:
- py-clob-client v0.34.6,
signature_type=1 get_balance_allowance()confirms $222.45 balanceget_ok()returnsTrue- All order sizes fail: $1, $5, $10
update_balance_allowance()returns empty (no effect)- Previously worked intermittently — some orders succeeded, some failed with the same error, same session
Checklist — things to verify before blaming this bug:
from py_clob_client.client import ClobClient
from py_clob_client.clob_types import BalanceAllowanceParams, AssetType
# 1. Correct USDC.e contract? Must be 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174
# NOT the other USDC: 0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359
# 2. Correct funder address?
# For signature_type=1 (Magic): use your Polymarket deposit address
# For signature_type=2 (browser wallet): use your proxy address
# 3. Balance check
balance = client.get_balance_allowance(
BalanceAllowanceParams(asset_type=AssetType.COLLATERAL)
)
usdc_wei = int(balance["balance"])
usdc = usdc_wei / 1e6
print(f"Balance: ${usdc:.2f}")
# 4. Allowance check
allowance = int(balance.get("allowance", "0"))
print(f"Allowance: {allowance}")
# Should be a very large number (MAX_UINT256)
# If zero, you need to set allowances first
# 5. Try regenerating API credentials
client.set_api_creds(client.create_or_derive_api_creds())
Workaround: No reliable workaround exists. Some users report success after regenerating API credentials, switching signature_type, or waiting and retrying hours later. This appears to be a CLOB backend state synchronization issue.
Issue #265 — Cannot Sell Full Position (Fractional Shares Below Minimum)
Opened: February 9, 2026
Status: Open
Affects: create_market_order() with SELL, create_order() with SELL
After buying shares on fee-enabled markets (especially 15-minute crypto markets), taker fees reduce your actual token balance below the reported size_matched. When you try to sell your full position, the final fractional amount falls below the market’s minimum order size, and the API rejects it.
Example scenario:
- Buy 5 shares of BTC 15-min Up at $0.50 → API reports
size_matched: 5 - Taker fee deducts ~0.5 shares → actual balance: ~4.5 shares
- Sell 4.5 shares via API → succeeds
- Try to sell remaining 0.5 shares → fails:
PolyApiException[status_code=400, error_message={'error': 'order ... is invalid. Size (0.1) lower than the minimum: 5'}]
- The Polymarket UI can still sell the remaining 0.5 shares — only the API enforces this minimum
Workaround: Sell via the Polymarket web UI for the final fractional amount. Or, when calculating sell size, subtract the expected fee deduction and only sell the amount you know exceeds the minimum:
# Before selling, account for the fee gap
positions = client.get_positions()
for pos in positions:
size = float(pos["size"])
# Fetch market minimum
min_size = get_min_order_size_for_token(pos["asset"]["token_id"])
sellable = size if size >= min_size else 0
if sellable > 0:
order = OrderArgs(
token_id=pos["asset"]["token_id"],
price=target_price,
size=sellable,
side=SELL
)
signed = client.create_order(order)
client.post_order(signed, OrderType.GTC)
Related: Issue #245 covers the root cause — size_matched does not account for fee deductions.
Issue #245 — size_matched Does Not Reflect Taker Fee Deductions
Opened: January 15, 2026
Status: Open
Affects: post_order() response, position size calculations
On fee-enabled markets (crypto, sports, etc.), the size_matched field in the order response shows the full order size, but the actual conditional tokens received are reduced by the taker fee. This means your agent’s position tracking is wrong if you rely on size_matched as your actual share count.
Example:
response = client.post_order(signed, OrderType.FOK)
print(response["size_matched"]) # Shows "5.0"
# But actual tokens received: ~4.95 (after fee deduction)
# Check real position via Data API
import requests
resp = requests.get(
f"https://data-api.polymarket.com/positions?user={address}"
)
for p in resp.json():
print(f"Actual size: {p['size']}") # Shows 4.95
Workaround: After any fill on a fee-enabled market, query actual positions via the Data API or get_positions() rather than trusting the size_matched value from post_order(). This is especially critical for agents that use size_matched to calculate sell order sizes.
Issue #300 — get_balance_allowance() Returns Inconsistent Results
Opened: March 16, 2026 by FireLoveInIce
Status: Open
Affects: get_balance_allowance(), pre-trade validation
Consecutive calls to get_balance_allowance() with the same BalanceAllowanceParams return different balance values. This makes pre-trade balance validation unreliable — your agent may reject a valid trade or attempt an invalid one.
Workaround: Call get_balance_allowance() multiple times and use the median or most recent value. Or validate against on-chain state directly using web3.py:
from web3 import Web3
w3 = Web3(Web3.HTTPProvider("https://polygon-rpc.com"))
usdc_contract = w3.eth.contract(
address="0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
abi=[{"inputs":[{"name":"account","type":"address"}],
"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],
"stateMutability":"view","type":"function"}]
)
balance_wei = usdc_contract.functions.balanceOf("YOUR_ADDRESS").call()
balance_usdc = balance_wei / 1e6
print(f"On-chain balance: ${balance_usdc:.2f}")
Issue #299 — macOS Installation Fails on Python 3.13
Opened: March 16, 2026 by isomare
Status: Open
Affects: pip install py-clob-client on macOS with Python 3.13
The ckzg dependency fails to build a wheel on Python 3.13, blocking installation entirely. This does not affect Python 3.9–3.12.
Workaround: Use Python 3.12 or earlier. If you need 3.13, try installing ckzg from a pre-built wheel first:
# Use Python 3.12
python3.12 -m pip install py-clob-client==0.34.6
# Or pin ckzg separately if you must use 3.13
pip install ckzg==1.0.2 # Try an older version with pre-built wheels
pip install py-clob-client
Issue #295 — Cannot Redeem Closed Market Positions
Opened: March 9, 2026 by Antondivnich Status: Open Affects: Post-settlement redemption
After a market resolves, the SDK provides no working method to redeem winning positions. The redeem() method (if called directly on the CTF contract) sends 0 USDC back. The Polymarket UI also sometimes fails to show a redeem button.
Workaround: Interact directly with the CTF (Conditional Token Framework) contract on Polygon to redeem. This requires web3.py and the CTF ABI. See the Polymarket CLOB API docs for the contract addresses and redemption flow.
Issue #297 — Proxy Wallet Allowances Stuck at Zero
Opened: March 15, 2026 by laulopezreal
Status: Open
Affects: post_order() for proxy wallet users
Even after running the allowance-setting script, the CLOB reports zero allowance for proxy wallets. Orders fail with not enough balance / allowance.
Workaround: Verify you are approving the correct contracts for the correct address. The CTF Exchange contract address and the USDC.e address must both be approved. If using signature_type=1, ensure your allowances are set on the proxy address (not the signing key address). See the Polymarket Coinbase quickstart guide for the full allowance setup flow.
Open PRs to Watch
The repository has 56 open pull requests as of April 2026. Three are particularly relevant for order placement:
- PR #313 — Type hint improvements across the SDK. Will improve IDE autocompletion and catch type errors at write time rather than runtime.
- PR #312 — Migration from
setup.pytopyproject.toml. Modernizes the build system but could change installation behavior. - PR #308 — Enum fixes. May resolve issues where
OrderType.GTCorOrderType.FOKare not properly recognized in certain Python versions.
None of these PRs have been merged. There has been no new release since v0.34.6 (February 19, 2026).
Defensive Coding Patterns
Given the volume of open bugs, production agents should adopt defensive patterns around every order placement call:
import time
from py_clob_client.exceptions import PolyApiException
def safe_post_order(client, signed_order, order_type, max_retries=3):
"""Post order with retry logic for known intermittent failures."""
for attempt in range(max_retries):
try:
response = client.post_order(signed_order, order_type)
# Don't trust size_matched on fee-enabled markets (#245)
# Verify actual position after fill
return response
except PolyApiException as e:
error_msg = str(e)
if "not enough balance / allowance" in error_msg:
# Known intermittent bug (#287)
# Retry after brief delay
if attempt < max_retries - 1:
time.sleep(2 ** attempt)
# Regenerate creds on last retry
if attempt == max_retries - 2:
client.set_api_creds(
client.create_or_derive_api_creds()
)
continue
if "lower than the minimum" in error_msg:
# Minimum size validation (#301 or #265)
# Don't retry — order size is the problem
raise
raise
raise Exception("Order failed after all retries")
Summary Table
| Issue | Error / Symptom | Affects | Workaround |
|---|---|---|---|
| #301 | size (X) lower than the minimum: Y | create_order() | Validate min size via Gamma API before ordering |
| #300 | Inconsistent balance values | get_balance_allowance() | Query on-chain balance with web3.py |
| #299 | ckzg wheel build fails | Installation on macOS + Python 3.13 | Use Python 3.12 |
| #297 | Allowance stuck at zero | Proxy wallet users | Verify correct contract approvals on proxy address |
| #295 | Cannot redeem after market resolves | Post-settlement | Redeem directly via CTF contract with web3.py |
| #294 | Wrong trader_side on sells | get_trades() fee accounting | Infer maker/taker from your own order parameters |
| #293 | Trades invisible in UI | post_order() with mismatched addresses | Ensure funder matches Polymarket profile address |
| #287 | not enough balance / allowance | All post_order() calls | Retry with credential regeneration; no reliable fix |
| #265 | Cannot sell final fractional shares | Sell after fee-enabled buy | Sell remainder via Polymarket UI |
| #245 | size_matched overstates actual tokens | post_order() response | Check real position via Data API after fill |
Further Reading
- py_clob_client Complete Reference — Every method documented with known issues
- py_clob_client create_order() Guide — Order placement deep dive
- py_clob_client get_balance_allowance() Guide — Balance checking patterns
- py_clob_client get_positions() Guide — Position tracking after fills
- Polymarket API Tutorial — Full API walkthrough
- Polymarket Auth Troubleshooting — Fix POLY header and signature errors
- Polymarket Rate Limits Guide — Handle 429 errors when retrying failed orders
- Security Best Practices — Protecting your API keys and wallet
- GitHub Issues Page — Full issue tracker
