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 balance
  • get_ok() returns True
  • 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:

  1. Buy 5 shares of BTC 15-min Up at $0.50 → API reports size_matched: 5
  2. Taker fee deducts ~0.5 shares → actual balance: ~4.5 shares
  3. Sell 4.5 shares via API → succeeds
  4. 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'}]
  1. 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.py to pyproject.toml. Modernizes the build system but could change installation behavior.
  • PR #308 — Enum fixes. May resolve issues where OrderType.GTC or OrderType.FOK are 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

IssueError / SymptomAffectsWorkaround
#301size (X) lower than the minimum: Ycreate_order()Validate min size via Gamma API before ordering
#300Inconsistent balance valuesget_balance_allowance()Query on-chain balance with web3.py
#299ckzg wheel build failsInstallation on macOS + Python 3.13Use Python 3.12
#297Allowance stuck at zeroProxy wallet usersVerify correct contract approvals on proxy address
#295Cannot redeem after market resolvesPost-settlementRedeem directly via CTF contract with web3.py
#294Wrong trader_side on sellsget_trades() fee accountingInfer maker/taker from your own order parameters
#293Trades invisible in UIpost_order() with mismatched addressesEnsure funder matches Polymarket profile address
#287not enough balance / allowanceAll post_order() callsRetry with credential regeneration; no reliable fix
#265Cannot sell final fractional sharesSell after fee-enabled buySell remainder via Polymarket UI
#245size_matched overstates actual tokenspost_order() responseCheck real position via Data API after fill

Further Reading