Skip to content
SOLTidy

Can't close a Solana token account? Errors and fixes

Can't close a Solana token account? The exact errors, from 'balance is zero' to 'Account is frozen' and withheld fees, what each means, and how to fix it.

Cover image for Can't close a Solana token account? Errors and fixes
By 8 min read 1696 words

Key takeaways

  • The most common reason a Solana token account will not close is a leftover balance: CloseAccount fails with 'Non-native account can only be closed if its balance is zero', custom program error 0xb, until the tokens are sold, sent or burned.
  • A Solana token account whose close authority is set to another address can only be closed by that address, and closing it from the owner's wallet fails with 'owner does not match', custom program error 0x4.
  • A Token-2022 account holding withheld transfer fees fails to close with custom program error 0x23 until the fees are harvested to the mint, which anyone can do.
  • A frozen Solana token account with a balance cannot be emptied because burning and transferring fail with 'Account is frozen', 0x11; only the token's freeze authority can thaw it.
  • A wallet with no SOL cannot close its token accounts, because the network fee is charged before the rent is returned; about 0.00001 SOL is enough to start.

The short answer

A Solana token account will not close when it still holds tokens (error 0xb), when another address is its close authority (0x4), when a Token-2022 account holds withheld transfer fees (0x23), when it is frozen with a balance you cannot burn (0x11), or when your wallet has no SOL for the 5,000-lamport fee. Empty it, harvest the fees, or fund the wallet, and it closes.

Why won't my Solana token account close?

A token account closes only when the token program's checks pass, and every failure maps to one of them. Reading CloseAccount in the SPL Token and Token-2022 source, the program checks that:

  1. The balance is zero, unless the account is wrapped SOL.
  2. The signer is the owner, or the close authority if one is set.
  3. For Token-2022 only: no withheld transfer fees remain, and any confidential balance is zero.

That is the whole list. The program does not check delegates, and it does not check the frozen flag, which surprises people. Everything else that goes wrong is about getting to an empty account, or about paying for the transaction. Exact error text matters here, because each one points at a different fix.

What do the token account close errors mean?

The table lists the error text from the token program source, how it appears in a failed transaction, and what to do. Codes are the same in both programs up to 0x13; the higher ones exist only in Token-2022.

Error text in the logsCodeCauseFix
Error: Non-native account can only be closed if its balance is zero0xbTokens left in the account, often dustSell, send or burn the balance, then close
Error: owner does not match0x4The signer is not the owner or the close authoritySign with the right wallet, or the close authority
missing required signature for instructionruntimeThe authority did not signSign with the owner or close authority
Error: An account can only be closed if its withheld fee balance is zero, harvest fees to the mint and try again0x23Token-2022 transfer fees withheld in the accountHarvest to the mint, then close
Error: An account can only be closed if its confidential balance is zero0x17Token-2022 confidential balance not emptyApply pending balance, withdraw, then close
Error: Account is frozen0x11Burning or sending from a frozen accountOnly the freeze authority can thaw it
Transferring, minting, and burning is paused on this mintToken-2022The mint is paused, so the balance cannot be burnedWait for the token to be unpaused
Attempt to debit an account but found no record of a prior credit.transactionThe wallet holds no SOL for the feeSend a little SOL to the wallet
Insufficient funds for feetransactionThe wallet has less SOL than the feeSend a little SOL to the wallet
invalid account data for instruction / incorrect program id for instructionruntimeUsually the account is already closedRefresh; nothing to do

The "Error:" lines are what the token programs write to the transaction logs. The custom program error line next to them, such as custom program error: 0xb, is the same error as a number. A code only means something inside the program that raised it, so check whether it was SPL Token or Token-2022 first.

How do you fix "balance is zero" errors on a dust balance?

Remove the balance, then close. This is the most common failure by far, because wallets often round tiny balances to zero or hide the token, while the account still holds a few base units. Three ways to remove it:

  • Sell it if it has a market. Sell Dust for SOL quotes every small balance through Jupiter and closes the emptied account in the same transaction, for 5% of the SOL received plus 5% of the rent.
  • Send it to another wallet that wants it.
  • Burn it if it has no market. spl-token burn costs only the network fee; the Burn Tokens tool charges 0.005 SOL per burn transaction. In the Token Account Closer you can tick a non-empty account, and it burns the balance before closing, with a red warning first. Burning is permanent.

What if someone else is the close authority?

Then only that address can close the account, and only it receives the rent. A close authority is an optional setting on a token account; when set, it replaces the owner for CloseAccount. Ordinary wallets rarely have one, but accounts created by some programs or services may. Closing from the owner's wallet fails with "owner does not match".

To see which of your accounts have one, run spl-token accounts --externally-closeable. If you control the authority, sign with it, or use spl-token close --close-authority <KEYPAIR>. If you do not, the rent in that account is not yours to recover.

Do not confuse this with a delegate. A delegate is an approval to move your tokens, and it does not block closing. If you want to clean up old approvals on accounts you keep, the free Revoke Delegations tool lists them for any address.

How do you close an account with withheld Token-2022 fees?

Harvest the withheld fees to the mint first. Tokens with the Token-2022 transfer fee extension leave each fee inside the recipient's account, in a field separate from your balance. Your balance can be zero while that field is not, and the program refuses the close with error 0x23.

HarvestWithheldTokensToMint is permissionless, so your wallet can send it. spl-token close --address <ACCOUNT> sends the harvest first automatically, and so does the SOLTidy closer, in the same transaction as the close. The details for every Token-2022 extension are in how to close Token-2022 accounts. If you are the token's creator rather than a holder, harvesting and withdrawing those fees is covered in setting and claiming Token-2022 transfer fees.

What can you do about a frozen token account?

It depends on whether it holds tokens. A frozen account with a balance is stuck: burning and transferring both fail with "Account is frozen", and only the token's freeze authority can send the thaw instruction. On scam tokens that freeze buyers, that will not happen, so treat the rent as lost and the lesson as the useful part; mint authority vs freeze authority explains how to spot a live freeze authority before buying.

An empty frozen account is different. In the current SPL Token and Token-2022 source, CloseAccount does not check the frozen flag, so the owner should be able to close it with spl-token close --address <ACCOUNT>. I have not tested this against every token, so treat it as what the code says rather than a promise. SOLTidy does not list frozen accounts at the moment, and spl-token gc skips them too.

What if the wallet has no SOL for the fee?

Add a small amount of SOL. Solana deducts the network fee before running any instruction, so the rent a close would return cannot pay for the close itself. A wallet with no SOL at all gets "Attempt to debit an account but found no record of a prior credit." A wallet with a few lamports gets "Insufficient funds for fee". The base fee is 5,000 lamports per signature, so about 0.00001 SOL is enough to start; after the first transaction the recovered rent covers the rest. This often happens with old trading-bot wallets that were swept of SOL but not of token accounts, covered in reclaiming SOL from trading bot wallets.

How does SOLTidy's closer avoid failed closes?

It checks before you sign, so a failure becomes a skipped account rather than a failed transaction. From the code:

  1. The scan covers SPL Token and Token-2022, and only accounts your wallet can close right now are listed. Frozen accounts, accounts with a different close authority and confidential transfer accounts are left out.
  2. Empty accounts are pre-selected. Non-empty ones are burned and closed only if you tick them.
  3. Withheld Token-2022 fees are harvested in the same transaction as the close.
  4. Right before sending, every batch of up to 12 items is simulated. If a batch would fail, each item in it is simulated on its own, the ones that fail are dropped, and the rest are re-packed. The result says how many accounts "changed since the scan" and were skipped.
  5. If the failure is not about any one account, typically no SOL for the fee, nothing is sent and you are asked to add about 0.00001 SOL.

The fee is 5% of the rent recovered, charged per transaction inside that transaction, and nothing when nothing is recovered. There are no token approvals and any Solana wallet works. For one or two accounts, spl-token close or a wallet's own menu is free apart from network fees; the commands, including spl-token gc, are in closing Solana token accounts with the CLI.

How do you read why a close failed?

Look up the failed transaction and read its logs from the bottom. The free Transaction Decoder does this for any mainnet signature without a wallet:

  1. Copy the signature from your wallet's activity list.
  2. Paste it into the decoder or an explorer. Not found after a couple of minutes means it never landed and cost nothing.
  3. Find the failed instruction and the program that raised it, SPL Token or Token-2022.
  4. Read the "Error:" log line and the custom program error code, and match them to the table above.

General transaction failures, such as expired blockhashes and priority fees, are covered in why Solana transactions fail.

Bottom line

When a Solana token account will not close, the error text tells you which check failed. A leftover balance (0xb) means sell, send or burn first. "Owner does not match" (0x4) means another address holds the close authority. 0x23 means Token-2022 fees need harvesting, which anyone can do. A frozen account with a balance is stuck until the freeze authority thaws it, and a wallet with no SOL needs a few thousand lamports before anything else works. Fix the cause, or let the SOLTidy closer list only the accounts that can close right now and skip the rest.

Questions & answers

What does "Non-native account can only be closed if its balance is zero" mean?

It means the token account still holds some of its token, even a tiny fraction you cannot see in your wallet. It is error 11, shown as custom program error 0xb, in both the SPL Token and Token-2022 programs. Sell the balance if it has a market, send it to another wallet, or burn it, and the close will then succeed. Wrapped SOL is the one exception: it can close with a balance.

Can a frozen token account be closed?

If it is empty, the program allows it: neither token program's CloseAccount checks the frozen flag in the current source, so the owner can close an empty frozen account. If it holds tokens, no. Burning and transferring from a frozen account both fail with 'Account is frozen', so the balance cannot be removed until the token's freeze authority thaws the account, and on scam tokens it rarely will.

Does a token delegate stop me from closing an account?

No. A delegate is permission for another address to move your tokens, and CloseAccount does not check it. Once the account is empty you can close it, and the delegate approval disappears with the account. What does block closing is a close authority set to another address, which is a different setting. Use a delegation scan if you want to see and revoke delegates on accounts you keep.

Why does closing fail with "Attempt to debit an account but found no record of a prior credit"?

Your wallet holds no SOL at all, so it cannot pay the network fee. Solana charges the fee before any instruction runs, including the close that would return rent. Send a small amount of SOL to the wallet first; about 0.00001 SOL covers the 5,000-lamport base fee of one or two transactions. On the command line, another wallet can pay with the --fee-payer option.

Why did some accounts get skipped when I used a closing tool?

Usually because they changed between the scan and the signature, for example a trading bot closed or refilled them, or because they cannot be closed by your wallet at all, such as frozen accounts or ones with a foreign close authority. The SOLTidy closer simulates every batch right before you sign, drops accounts that would fail, and tells you how many were skipped.

What does custom program error 0x23 mean when closing a token account?

In the Token-2022 program, 0x23 is error 35, AccountHasWithheldTransferFees: the account still holds transfer fees withheld from tokens you received. Harvest them to the mint with the permissionless HarvestWithheldTokensToMint instruction, then close. The spl-token close command and the SOLTidy closer both add the harvest automatically.

How do I find out exactly why my close transaction failed?

Look up the transaction signature in an explorer or a decoder and read the program logs from the bottom. The token program logs a line starting with 'Error:' followed by the reason, and the failure line shows the custom program error code. Match the code against the table in this article, keeping in mind which of the two token programs raised it.