Why getProgramAccounts returns an empty array
Last updated:
At a glance
| Property | Value |
|---|---|
| What you get back | "result": [] — no account passed every filter |
| Filter logic | AND across all filters, up to 4 |
| memcmp bytes | base58 by default; base64 when encoding is set; decoded data limited to 128 bytes |
| Classic SPL token account | 165 bytes; mint at offset 0, owner at offset 32 |
| Token-2022 | A separate program ID; extension accounts are longer than 165 bytes |
What you see
You call getProgramAccounts for a program ID with a dataSize and a memcmp filter — for example to list the token accounts of a wallet — and the response is "result": [], even though you can see matching accounts in an explorer. Removing a filter returns data, or a huge list.
Why this happens
getProgramAccounts returns accounts owned by the program ID you pass, and filters combine with AND logic: an account is returned only if it matches every filter (up to four). dataSize matches the exact length of the account data in bytes; one wrong size excludes everything. memcmp compares bytes at an offset in the account data; the offset must match the program's layout, and bytes are read as base58 unless you set encoding to base64, with decoded data limited to 128 bytes. A value encoded one way and read the other way silently matches nothing. For SPL tokens there is a second trap: the classic Token program and Token-2022 are different programs with different program IDs, so accounts created by one never show up when you query the other. In the classic layout a token account is 165 bytes, with the mint at offset 0 and the owner at offset 32; Token-2022 accounts that use extensions are longer, so a dataSize of 165 filters them out.
What to do
- Run the call with only the program ID and a small dataSlice to confirm the program owns accounts at all on this cluster.
- Add filters back one at a time — dataSize first, then each memcmp — to find the one that empties the result.
- Check each memcmp offset against the program's account layout, and make sure the bytes are base58 unless you explicitly set encoding to base64.
- For token accounts, query both the Token program and Token-2022, or use getTokenAccountsByOwner with the mint or program ID, which handles the owner filter for you.
- Rule out the wrong cluster: a program deployed on devnet has no accounts on mainnet-beta.
When this is not our problem
Filter matching is done by the Solana node against the account data exactly as your request describes it, so an empty result for a mismatched filter is the same on every provider, Triport included. Only the filter can be fixed.
FAQ
- Why does getProgramAccounts return nothing for my wallet's tokens?
- Most often the filter targets the wrong token program or the wrong size: Token-2022 accounts are not owned by the classic Token program, and accounts with extensions do not match dataSize 165. getTokenAccountsByOwner is usually the simpler call for this job.
- Are getProgramAccounts filters combined with AND or OR?
- AND. An account is returned only if it matches every filter in the array.