custom program error: 0x23
Error·3 min read
A Token-2022 account reads as zero but is not closeable, because the transfer fee extension parked withheld fees inside it. One extra instruction clears it.
Error 35, written 0x23, is AccountHasWithheldTransferFees from the Token-2022 program. Its own documentation gives you the fix: an account can only be closed if its withheld fee balance is zero, so harvest the fees to the mint and try again.
What are withheld fees?
Token-2022 lets a mint carry extensions, and one of them is a transfer fee. When a mint uses it, every transfer of that token has a percentage skimmed off and parked inside the recipient account rather than sent onward immediately. The mint authority later collects it.
So after you sell out of such a token, the account can read as zero tokens while still holding withheld fees that belong to the mint. The token program will not let you close an account that is sitting on somebody else's fees.
Why this catches people
The balance shows zero, the account looks finished, and the close fails anyway with a code that means nothing on sight. Most rent tools do not handle it: they list the account as reclaimable, build the close, and the whole transaction fails. If a cleanup keeps dying on one stubborn account, this is usually why.
How to clear it
One extra instruction before the close, sending the withheld amount back to the mint:
spl-token harvest-withheld-tokens <MINT> <TOKEN_ACCOUNT>
spl-token close --address <TOKEN_ACCOUNT>Harvesting is permissionless, which is the useful part. You do not need the mint authority's cooperation, because the fees are going where they were always going. Once the withheld balance is zero the account closes normally and the rent deposit comes back to you.
In a batched cleanup the harvest has to be grouped per mint and placed before the closes in the same transaction, otherwise the close still sees a non-zero withheld balance. SolanaSweeper does this automatically, which is worth saying plainly because most tools simply skip these accounts and quietly report a lower total.
Can I avoid the fee?
No. The transfer fee is set on the mint, it applies to every transfer including the one that moved the tokens out, and there is no opt-out on your side. It is not a charge from your wallet or from whatever tool you are using.
It is worth knowing about before you swap dust on a Token-2022 mint, because the fee comes out of the amount you are selling and can turn a marginal swap into a losing one. Burn or swap covers where that line sits.
Related failures
If the account also still holds actual tokens, you will meet 0xb first, which is the plain balance-not-zero refusal. Harvesting does not help there; you need to empty the account.
And if what you are seeing is the wrapper rather than the code, start at transaction simulation failed to find which error is actually underneath.