InvalidWritableAccount
A transaction marks an account as writable, but the runtime determined that this account must be read-only for this instruction.
Common causes
- System-owned executable account marked writable. Program accounts (executables) and native program accounts like the System Program, Token Program, or Clock sysvar cannot be marked writable.
- Wrong
isSignerorisWritableflags. The instruction’s account meta hasisWritable: truefor an account that the program expects to be read-only. - Sysvar passed as writable. Sysvars like Clock, Rent, and StakeHistory are always read-only.
How to fix
- Check account meta flags. Review your instruction builder and ensure read-only accounts have
isWritable: false:
{
pubkey: systemProgram,
isSigner: false,
isWritable: false, // programs are never writable
}
- Never mark program IDs as writable. Any program account passed in the instruction’s
programIdfield or as an invoked program is always read-only. - Check sysvar usage. Sysvars should always be read-only. If your program needs sysvar data, it can read it without the account being writable.
Accounts that are always read-only
- All executable program accounts
- Native programs (System, Token, Associated Token, Compute Budget)
- All sysvars (Clock, Rent, Fees, SlotHashes, StakeHistory, etc.)
- Accounts loaded through Address Lookup Tables with the read-only table section
FAQ
What happens if I mark a read-only account as writable? The transaction is rejected before execution. No fees are charged because the transaction fails pre-processing validation.
Does this affect CPI calls? Yes. If a program makes a CPI (Cross-Program Invocation) and passes an account as writable that was marked read-only in the outer instruction, the CPI will fail with this error.
Error text variants
-
InvalidWritableAccount -
invalid writable account -
cannot write to read-only account
Updated: