Solana Documentation Audit
The docs are deep and well-structured on concepts, and they ship the machine-readable scaffolding agents want (llms.txt, llms-full.txt, SKILL.md). But the "official SDK" story fractures across pages — the recommended quick-start installs packages that appear in no reference, the five "official" TypeScript SDKs don't share a client-creation idiom, the reference page's mainnet RPC URL isn't the one the rest of the docs use, and the RPC method pages ship no error-code contract.
1. The recommended quick-start uses SDK packages that exist in no reference list (critical)
Location: /docs/intro/quick-start/reading-from-network and /docs/intro/quick-start/writing-to-network
Problem: As scraped, both quick-start tutorials pull in @solana/kit-plugin-rpc and @solana/kit-plugin-signer and drive a createClient().use(...) builder. The canonical JS SDK reference (/docs/clients/official/javascript) lists the Kit packages as @solana/kit, @solana-program/*, and @solana/kit-plugins — there is no @solana/kit-plugin-rpc or @solana/kit-plugin-signer anywhere in that reference, and everywhere else Kit is invoked via createSolanaRpc(...) (e.g. /docs/payments/how-payments-work), not a .use(plugin) builder. The verifiable, docs-level fact is the mismatch: the packages the onboarding tutorial names are not the packages the reference documents.
Consequence: A developer — or an AI agent — following the officially "recommended" onboarding path is told to depend on packages that the SDK reference never lists and that don't match the createSolanaRpc idiom used on every other page. This is the first tutorial a new user hits, and nothing on the page marks these as hypothetical/future packages, so the install target can't be reconciled against the reference.
The fix: Rewrite both quick-start tutorials to the shipped @solana/kit API (createSolanaRpc(endpoint)), matching /docs/payments and /docs/clients/official/javascript. If a plugin builder is genuinely planned, gate the tutorial behind packages that actually publish, list them in the SDK reference, and add a version note.
2. The clusters reference uses a mainnet RPC URL the rest of the docs never use (critical)
Location: /docs/references/clusters
Problem: The clusters reference gives the mainnet endpoint as https://api.mainnet.solana.com (and gossip entrypoint.mainnet.solana.com:8001), in both the table and the "Mainnet endpoint" prose. This is not the canonical Solana mainnet host, which is api.mainnet-beta.solana.com — the form the payments material uses (createSolanaRpc("https://api.mainnet-beta.solana.com") on /docs/payments/how-payments-work). So the one page a developer visits specifically to copy the "official" endpoint list is the page that diverges from every place the URL is actually used.
Consequence: Copy the mainnet value from the clusters page and connections point at a host the rest of the site never references, while the payments snippet on the same site uses a different host — a silent, self-contradicting break that agents indexing both pages can't reconcile.
The fix: Correct the clusters table and prose to https://api.mainnet-beta.solana.com (and the matching gossip entrypoint), then grep the whole docs set to enforce a single mainnet host string.
3. Five "official" TypeScript SDKs, no canonical way to create a client (critical)
Location: /docs (landing SDK table), /docs/frontend/client, /docs/frontend/react-hooks, /docs/intro/quick-start/*
Problem: The landing table presents @solana/kit (recommended), @solana/client, @solana/react-hooks, and @solana/web3.js (legacy) all as official TypeScript SDKs, but they do not share a client-creation idiom. The recommended @solana/kit creates its RPC via createSolanaRpc(...) (/docs/payments/how-payments-work, /docs/clients/official/javascript). @solana/client instead exposes a createClient(...) "create a client once" surface (/docs/frontend/client). @solana/react-hooks is documented as a layer built "on top of @solana/client" (/docs/frontend/react-hooks) yet is listed as its own standalone official SDK. Nothing tells a reader which of these is the entry point, and createClient (client page) versus createSolanaRpc (kit) are two different idioms across two packages both stamped "official."
Consequence: There is no single answer to "how do I create a Solana client?" A developer can't tell which package is the front door, and an agent generating code will interleave call shapes from adjacent "official" pages (createClient vs createSolanaRpc) that don't compose.
The fix: Publish one canonical "create a client" idiom and label every other package's relationship to it (built-on, alternative, legacy) — e.g. state plainly that @solana/react-hooks wraps @solana/client, and that @solana/kit is the recommended standalone entry point using createSolanaRpc.
4. Keychain backend list disagrees between the Rust and JS references (significant)
Location: /docs/clients/official/rust vs /docs/clients/official/javascript, /docs/tools/keychain, /docs/core/transactions/signing-in-production
Problem: The Rust page lists Keychain's backends as "Memory, Vault, Privy, Turnkey, AWS KMS, Fireblocks, GCP KMS, CDP, Para, Dfns, Crossmint" — 11 backends. The JS page, the Keychain page, and signing-in-production all list 13, adding Openfort and Utila. The Keychain page itself states Rust and TypeScript are "at full parity."
Consequence: A Rust backend team choosing a signing provider will believe Openfort and Utila are unsupported in Rust and architect around a limitation that (per the parity claim) doesn't exist — or vice versa if the Rust list is the accurate one. Either way one page is wrong and the "full parity" claim can't be trusted.
The fix: Generate the backend list from a single source and render it identically on both language pages; if parity genuinely differs, replace the blanket "full parity" claim with a per-backend support matrix.
5. Keychain claims @solana/signers compatibility, but that package is in no SDK reference (significant)
Location: /docs/tools/keychain vs /docs/clients/official/javascript
Problem: The Keychain page's compatibility line states Keychain is "@solana/kit and @solana/signers compatible (TypeScript)." But @solana/signers appears in no SDK reference — /docs/clients/official/javascript lists @solana/kit, @solana-program/*, @solana/kit-plugins, @solana/client, @solana/react-hooks, @solana/keychain, and @solana/web3.js, with no @solana/signers.
Consequence: A developer told Keychain is @solana/signers-compatible has no documented package entry explaining what @solana/signers is, when to use it, or how it relates to @solana/kit — the referenced dependency resolves to nothing discoverable in the docs.
The fix: Either add @solana/signers to the JS SDK reference with a description and GitHub link, or drop the @solana/signers compatibility claim in favor of a package that is actually documented.
6. The "Transfer SOL" tutorial links the System Program to an anchor that doesn't exist (significant)
Location: /docs/intro/quick-start/writing-to-network
Problem: The writing-to-network page links the System Program to /docs/core/programs#the-system-program. The ## The System Program heading actually lives on /docs/core/programs/builtin-programs, not on /docs/core/programs (whose sections are "Program Execution / Program Deployment / Core Programs / Precompiles / Syscall Reference"). The sibling reading-from-network page links the correct target, /docs/core/programs/builtin-programs#the-system-program — so two adjacent tutorials point the same concept at two different URLs, and one lands on a page with no matching anchor.
Consequence: A reader clicking through to understand the System Program gets dumped at the top of the wrong page with no scroll-to-section, right as they're learning how transfers work. Two different link targets for the same term also undermine agent link-following.
The fix: Point both quick-start pages at /docs/core/programs/builtin-programs#the-system-program and add a link-check to catch anchors that don't resolve on their target page.
7. getAccountInfo documents a deprecated encoding as its default (significant)
Location: /docs/rpc/http/getaccountinfo
Problem: The encoding parameter's !default is binary, but the same table marks binary as "⚠️ Deprecated … Use base64 instead," and dataSlice is documented as working with the deprecated binary encoding. Meanwhile /docs/rpc/http/sendtransaction defaults encoding to base58 — so two of the most-used methods default differently, and one defaults to a value the docs tell you not to use.
Consequence: A caller who omits encoding on getAccountInfo silently gets the deprecated, base58-limited (128-byte) format, then hits the "account data too large" limitation the deprecation note is trying to steer them away from. Agents that read defaults literally will emit deprecated calls by default.
The fix: Change the documented default to base64 (or whatever the node actually defaults to today) and remove binary from the dataSlice-supported list, or explicitly state the real runtime default and stop presenting a deprecated value as the recommended path.
8. No error-code contract anywhere in the RPC reference (significant)
Location: /docs/rpc/http (index) and per-method pages (e.g. /docs/rpc/http/getaccountinfo, /docs/rpc/http/sendtransaction)
Problem: The RPC HTTP index enumerates 50+ methods but documents no error responses, no error codes, and no default commitment; it just directs readers to individual method pages. The method pages then describe failure in prose (sendTransaction: "preflight → Simulation Results structure") with no enumerated JSON-RPC error-code list, and getAccountInfo has no error section at all. The only error codes in the whole set are the HTTP 403/429 notes on /docs/references/clusters.
Consequence: A developer building retry/error-handling logic has no reference for which JSON-RPC error codes a method can return or what they mean — they must trigger failures empirically. For agents this is worse: error handling is exactly the code they can't infer without a spec, so they generate happy-path-only clients.
The fix: Add a global JSON-RPC error-code reference (code, meaning, retriable?) and, per method, list the errors it can return. Surface the standard error envelope on the RPC HTTP index.
9. The Anchor framework page — a top-level nav item — is an empty stub (significant)
Location: /docs/programs/anchor
Problem: Anchor is the "leading development framework" per the page's own copy and it's a top-level Program Development nav entry, but the page is only an intro paragraph plus two link cards ("Installation," "Quickstart"). There is no actual framework documentation on it, in sharp contrast to the depth of the /docs/core concept pages.
Consequence: A developer navigating to the framework most Solana programs are written in finds a signpost, not documentation, and must leave the official docs for real Anchor material. The nav promises a section that isn't there.
The fix: Either build out the Anchor section (accounts, macros, IDL, testing, CPI-in-Anchor) or, if the content intentionally lives in Anchor's own docs, make that explicit and link out prominently instead of presenting a hollow local page.
10. signing-in-production depends on a transaction-structure page that isn't in the site map (significant)
Location: /docs/core/transactions/signing-in-production
Problem: This page's prerequisites frontmatter points to /docs/core/transactions/transaction-structure and its body links /docs/core/transactions/transaction-structure#signatures ("A transaction only executes if it carries a valid signature from every required signer"). But llms.txt — the site's own route map — lists /docs/core/transactions and /docs/core/transactions/signing-in-production as first-class pages and does not list transaction-structure, even though it does list other sub-paths like builtin-programs.
Consequence: The stated prerequisite and the "valid signature" link likely resolve to a missing page, breaking the reading order for exactly the security-sensitive production-signing topic. Because the route is absent from llms.txt, agents indexing the site won't discover it either.
The fix: Confirm whether /docs/core/transactions/transaction-structure exists; if it does, add it to llms.txt; if it doesn't, repoint the prerequisite and signature link to /docs/core/transactions (or wherever the signatures section actually lives).
11. The one-line installer is served from a workers.dev subdomain, per the installation page (significant)
Location: /docs/intro/installation
Problem: The installation page presents a single command to "install all the necessary dependencies" (Solana CLI, Rust, Node, etc.). As scraped, that installer script is served from solana-install.solana.workers.dev — a *.workers.dev Cloudflare Workers subdomain — rather than an solana.com or anza.xyz origin, and the page shows no checksum, signature, or explanation of the host alongside it.
Consequence: Developers are asked to run a one-command install of a CLI, Rust, and Node with no provenance shown on the page. A *.workers.dev name is not a strong first-party signal, and the pattern trains users to accept installer scripts from non-primary domains — a supply-chain footgun for a bootstrap tool.
The fix: Serve the installer from an official first-party domain (e.g. a release.solana.com / anza.xyz path), or publish a checksum/signature and document the host on the page so the provenance is verifiable.
12. Two different "builtin instruction" CU numbers appear across pages (minor)
Location: /docs/core/fees vs /docs/core/programs/builtin-programs
Problem: The Fees limits table lists "Builtin instruction default CU | 3,000 | MAX_BUILTIN_ALLOCATION_COMPUTE_UNIT_LIMIT," while the builtin-programs page states the System Program "consumes DEFAULT_COMPUTE_UNITS (150 CUs) per instruction." Both are framed around "builtin" compute units with no cross-reference explaining that one is an allocation cap and the other is actual consumption.
Consequence: A developer sizing compute budgets sees "3,000" on one page and "150" on another for what reads like the same thing, and can't tell which applies to a System Program transfer.
The fix: Disambiguate the labels ("default CU allocation for builtins" vs "CUs actually consumed") and cross-link the two constants so the relationship is explicit.
13. SPL Token Basics is a two-sentence page fronting a related list, most of which isn't in the site map (minor)
Location: /docs/tokens/basics (and /llms.txt)
Problem: The page declares a related list of a dozen sub-pages (create-mint, create-token-account, mint-tokens, transfer-tokens, approve/revoke-delegate, set-authority, burn-tokens, sync-native, close/freeze/thaw-account), but the rendered body is two sentences plus a Metaplex callout — all substance lives in the sub-pages. Worse, llms.txt (the site's own route map) lists only /docs/tokens/basics, /docs/tokens/basics/create-mint, and /docs/tokens/extensions under Tokens; the other eleven related routes do not appear in the map. This is the same "absent from llms.txt ⇒ likely undiscoverable" signal flagged for transaction-structure in #10.
Consequence: A reader lands on the section's namesake page and finds a link farm with no orientation on which instruction to use when. Meanwhile agents indexing via llms.txt won't discover eleven of the twelve linked sub-pages, and any related route that doesn't actually exist becomes a dead link with no visible content to soften it.
The fix: Add a short orientation on this page (what each instruction group does and the typical order), verify every related sub-path resolves, and add the token-basics sub-pages to llms.txt (or confirm they're intentionally omitted).
14. Identical "(top-level + CPIs)" label attached to two different limits (minor)
Location: /docs/core/transactions vs /docs/core/programs, /docs/core/cpi
Problem: The Transactions limits table lists "Max executed instructions | 64 (top-level + CPIs) | MAX_INSTRUCTION_TRACE_LENGTH," while the Programs and CPI pages list "Max instruction stack depth | 5 (top-level + CPIs) | MAX_INSTRUCTION_STACK_DEPTH." The same parenthetical qualifier is pinned to two structurally different limits — a count of executed instructions (trace length) versus a nesting depth.
Consequence: A developer skimming limits tables across pages sees "(top-level + CPIs)" next to both "64" and "5" and can conflate a trace-length ceiling with a nesting-depth ceiling when reasoning about how many CPIs a transaction can make.
The fix: Differentiate the qualifiers (e.g. "total instructions executed, top-level + CPIs" vs "nesting depth, top-level + CPIs") so the two constants can't be read as the same limit.
15. Organization attribution and the Rust SDK's own name drift across pages (minor)
Location: /docs/references/clusters, /docs (landing SDK table), /docs/clients/official/rust, /docs/tools/keychain
Problem: The clusters page says "The Solana Labs organization operates" the public RPC endpoints; the landing page says the SDKs are "built by Anza"; the footer is "© 2026 Solana Foundation." Separately, the Rust SDK is labeled solana_sdk (underscore) in the landing table but referenced as solana-sdk (hyphen) on the Keychain page's Rust compatibility line.
Consequence: New readers get inconsistent signals about who runs what (relevant when deciding whom to trust for RPC/SDK), and the solana_sdk/solana-sdk split blurs the line between the crate name and the import path for someone adding the dependency.
The fix: Standardize the operating-org language per surface (RPC operator, SDK maintainer, site owner), and present the Rust crate consistently as solana-sdk, noting the solana_sdk import form once where relevant.
What they do well
- Ships the agent-readable scaffolding most sites lack — llms.txt, llms-full.txt, SKILL.md, and Agent skills are all present and linked.
- The core concept pages (accounts, transactions, programs, CPI, fees) back nearly every limit with a named constant and source, which is exactly the parseable structure agents and careful developers want.
- Program IDs are internally consistent where it matters most — the Token, Token-2022, and System Program IDs match across payments, terminology, and builtin-programs.
Top 3 recommendations
- Fix the recommended onboarding path first. Make the quick-start use the real, published
@solana/kit/createSolanaRpcAPI and name one canonical client-creation idiom, so the first tutorial a new user or agent runs matches the reference it's supposed to teach. - Single-source the cross-page facts that currently disagree — the mainnet RPC URL, Keychain's backend list, the SDK package names, and the shared limit labels — and add a link/anchor checker so contradictions like the System Program mislink and the missing
transaction-structurepage surface in CI. - Give the RPC reference an error contract. Add a global JSON-RPC error-code table plus per-method error sections and consistent, non-deprecated encoding defaults, so developers and agents can build real error handling instead of happy-path-only clients.