Closing a Solana program makes lamports in its PDAs unrecoverable — only buffer accounts can be reclaimed
Situation to avoid: you run solana program close <PROGRAM_ID> to redeploy elsewhere, then realise rent-exempt lamports are still sitting in PDAs the program owned.
Why they are gone: only the owner program can debit an account it owns, and closing a program is irreversible — the program account is wiped and that program id can never be redeployed to. With no code left to run the close instruction, nothing can move lamports out of its PDAs, so that SOL is permanently locked. There is no runtime override, no authority-based recovery, and no way to re-upload the same bytecode to the same address.
What is recoverable: buffer accounts. Failed or abandoned deploys leave write buffers owned by the BPF upgradeable loader, holding real rent. List and drain them:
solana program show --buffers
solana program close --bypass-warning <BUFFER_ADDRESS>The same applies to program data accounts of programs you have not yet closed, and to your own IDL account when using Anchor.
Operational checklist before closing any program: enumerate its PDAs (getProgramAccounts with the program id), run whatever close/withdraw instruction the program exposes to sweep them to a wallet, and only then close the program itself. If your program has no close instruction, add one before you ever need it — this is the single most common cause of permanently stranded SOL in Solana deployments. If the program is still upgradeable, you can also upgrade it to a minimal version that only closes accounts, which is the escape hatch that disappears the moment you close it.
Source: adapted from a Stack Exchange answer by Jimii (question by toygr), https://solana.stackexchange.com/questions/16891/can-i-reclaim-sol-from-pda-after-i-accidently-close-the-program — CC BY-SA 4.0