Solana Fall School · Guide 01

Get your machine ready to ship a program.

Install four tools, prove each one works, then put Monday's lecture to work: send a real transaction, derive a PDA, and deploy a real program. Everything here is hands-on practice for material you have already been taught.

Time
60–90 min
OS
macOS · Linux · WSL
Networks
Localnet · Devnet
Checkpoints
10

How to use this page

Work top to bottom. Every checkpoint ends with a command that prints something, and the page tells you what to expect.

If your output does not match, stop there. A broken tool carried forward throws its error three checkpoints later, pointing at the wrong thing.

Tick each checkpoint as you go. Progress is saved in this browser, so you can close the tab and come back.

On Windows, install WSL first Anchor does not run on Windows natively, so you need Ubuntu through WSL — Solana lists it as a prerequisite. Checkpoint 0 covers it, or follow the official installation guide instead.

What you are actually installing

Four separate tools that people treat as one thing called "Solana". Knowing which is which is most of your debugging skill for the term.

rustcThe Rust compiler. Your program is Rust, compiled to SBF bytecode.
solanaThe CLI from Anza. Keys, cluster config, transactions, deploys.
anchorThe framework. Removes boilerplate, generates the client IDL.
nodeRuns the TypeScript tests and client scripts that call your program.

When something breaks, name the tool first. anchor build failing is usually rustc or a missing system library, not Anchor.

Where your code runs

Three networks, all running the same software. What changes is who can see them and what the SOL is worth. A cluster is just one of these networks — the word comes up constantly.

localnetdevnetmainnet
SOLFree, unlimitedFaucet, rate limitedReal money
SpeedInstantReal network conditionsReal network conditions
PersistenceWiped on every restartPersistentPermanent
Visible to othersNoYes, shareable explorer linkYes
Use it for~95% of developmentIntegration testing, demos, sharingProduction
Localnet is your default, not devnet

Almost all of your development time this term happens on localnet — a Solana network running on your own laptop.

Localnet SOL is free and unlimited. No faucet, no airdrop request, no waiting.

It is also worthless, and it cannot move to devnet or mainnet. These are separate chains that share nothing.

Nobody else can see your localnet. That is the only reason this guide touches devnet at all — devnet gives you a link other people can open.

anchor test starts and stops its own local validator automatically. You never manage one.

00
Before anything else

Prepare your OS

When you finish this: your machine has the system libraries every later step depends on.

Everything after this checkpoint is identical on all three platforms. Do only the block that matches your machine, then rejoin at checkpoint 1.

Windows

Solana tooling does not run on Windows natively. WSL gives you a real Ubuntu inside Windows. Run this in PowerShell as administrator:

wsl --install

Reboot, then open the Ubuntu app from the Start menu and set a username and password.

From here on, "your terminal" means that Ubuntu window, never PowerShell. Run the Linux block below inside it.

Where you put your project matters

Keep your code in the Linux home directory (~/solana), not in /mnt/c/Users/....

Reading Windows files from WSL crosses a filesystem boundary. A cargo build that takes 90 seconds in ~ can take ten minutes on /mnt/c.

To edit in VS Code, install the WSL extension and open the folder from inside Ubuntu with code .

Linux and WSL

Anchor compiles from source and needs a C toolchain plus a few libraries. Missing these is the most common install failure.

sudo apt-get update
sudo apt-get install -y \
    build-essential \
    pkg-config \
    libudev-dev llvm libclang-dev \
    protobuf-compiler libssl-dev
If apt says protobuf-compiler is not available You skipped apt-get update. Run it and try again. On Fedora or RHEL the equivalents are gcc gcc-c++ pkgconf-pkg-config systemd-devel llvm clang-devel protobuf-compiler openssl-devel.

macOS

Install Apple's command line tools, which include the linker Rust calls.

xcode-select --install
xcode-select -p   # should print a path, not an error

If they were already installed, the first line says so and the second prints a path.

Do not install Rust with Homebrew

Use rustup instead — the next checkpoint does it for you. A Homebrew Rust lands in a directory Anchor does not search.

The failure shows up much later as No such file or directory (os error 2). If you already have one: brew uninstall rust.

01
The fast path

Install everything

When you finish this: all five tools installed and printing versions.

One script installs the whole toolchain. Try it first. If it completes, skip checkpoint 2 entirely.

curl --proto '=https' --tlsv1.2 -sSfL https://solana-install.solana.workers.dev | bash

It finishes by printing what it installed:

Installed Versions:
Rust: rustc 1.91.1 (ed61e7d7e 2025-11-07)
Solana CLI: solana-cli 3.0.10 (src:96c3a851; feat:3604001754, client:Agave)
Anchor CLI: anchor-cli 0.32.1
Surfpool CLI: surfpool 0.12.0
Node.js: v24.10.0
Yarn: 1.22.1

Surfpool is a local validator. The installer bundles it, this guide does not use it, and it comes up in a later class. Ignore it for now.

This takes 10 to 20 minutes

Most of that is compiling the Anchor CLI from source. The terminal looks frozen and your fan gets loud. That is normal.

Do not interrupt it. If you kill it halfway, you will need checkpoint 2 to finish the job by hand.

Close your terminal and open a new one. The script edited your shell profile and the current session has not read it.

Now check all five tools:

rustc --version && solana --version && anchor --version && \
node --version && yarn --version
Five lines of output

If all five print a version, you are done. Skip checkpoint 2 and go to checkpoint 3.

If a line says command not found, that one tool did not land. Install just that one from checkpoint 2.

02
Only if checkpoint 1 failed

The manual path

When you finish this: the tools checkpoint 1 missed, installed by hand.

Install one at a time, in this order, verifying each before moving on. Anchor depends on Rust and on the checkpoint 0 libraries, so order matters.

If only one tool is missing, jump straight to that block.

Rust

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
. "$HOME/.cargo/env"
rustc --version

Solana CLI

sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)"
solana --version
Aside Why it says client:Agave

The CLI is built by Anza and reports itself as client:Agave. Same tool — the validator client was renamed.

To update it later, run agave-install update, which pulls the newest stable release.

Hint solana: command not found after installing

PATH, essentially always. The installer printed a line and you did not run it. Find your shell first, because the file differs:

echo $SHELL   # /bash → .bashrc,  /zsh → .zshrc

Then append the line permanently and reload:

echo 'export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

Swap .bashrc for .zshrc if that is your shell. Typing export PATH=... directly into the terminal also works, but only until you close that window — which is why people think the install broke overnight.

Node and Yarn

Anchor's test template is TypeScript, so anchor test needs both.

Install Node through nvm rather than your system package manager, so you can switch versions per project.

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
# restart your terminal, then:
nvm install --lts
npm install -g yarn
node --version && yarn --version

Anchor, through AVM

Install the version manager, not the framework directly. Anchor makes breaking changes between minor versions, and you will eventually need two versions for two projects.

curl -sSfL https://raw.githubusercontent.com/otter-sec/anchor/master/avm/install | sh
avm --version

avm install latest
avm use latest
anchor --version
Two things people trip on here

avm install downloads a version. avm use is what points the anchor command at it. Skip the second and anchor --version keeps reporting the old one.

This build takes several minutes and needs the checkpoint 0 libraries. could not exec the linker cc means you skipped them.

TODO — author: verify this URL before publishing

The AVM installer URL has moved between repositories more than once. Check the line above against solana.com/docs/intro/installation/dependencies and update it before this guide is published.

Students: opening that page to confirm a URL before piping any script into your shell is a habit worth more than this guide.

03
Class baseline

Pin your versions

When you finish this: your versions match the rest of the class.

Solana tooling moves fast enough that a three-month-old blog post is often wrong. When forty people debug together, mismatched versions waste more time than any real bug.

Get onto these versions. If you cannot, say so in the channel before you ask for help.

TODO — author: confirm these pins before publishing The versions in the table below need to be checked against what the class is actually standardised on this term.
ToolCheckWe are onFix a mismatch
Rustrustc --version1.91.xrustup update stable
Solanasolana --version3.0.xagave-install update
Anchoranchor --version0.32.1avm install 0.32.1 && avm use 0.32.1
Nodenode --version22 or 24nvm install --lts

A patch-level difference is fine. A minor-version difference in Anchor is not.

0.31 and 0.32 generate different client code, and code from one will not compile against the other.

Save this line Start any help request with the output of the verify script at the bottom of this page. Half the replies you would otherwise get are "what version are you on".
04
Keys and clusters

Wallet and config

Network devnet

When you finish this: a wallet with about 5 devnet SOL in it, and a CLI pointed at devnet.

The CLI keeps one small config file. It decides which network your commands talk to and which keypair signs them.

Almost every "it worked yesterday" story is one of those two being different from what you assumed. Look at it first:

solana config get

You should see something like this:

Config File: /Users/you/.config/solana/cli/config.yml
RPC URL: https://api.mainnet.solana.com
WebSocket URL: wss://api.mainnet.solana.com/ (computed)
Keypair Path: /Users/you/.config/solana/id.json
Commitment: confirmed

Point at devnet

Switch the network your commands talk to:

solana config set --url devnet
solana config get   # confirm the RPC URL now says devnet

The RPC URL should now say devnet. Check it before you blame your code — this one line explains a lot of confusing errors.

Aside Short forms for switching cluster

solana config set -ud does the same thing as --url devnet. -um switches to mainnet and -ul switches to your local machine.

Create a keypair

Write a new keypair to the default path:

solana-keygen new
solana address

It prints a public key and a twelve-word seed phrase. That public key is your address on every Solana network at once.

Treat this key as disposable, and never commit it

id.json is an unencrypted private key sitting on disk. Fine for a course where it only holds test SOL. Not fine for anything with value.

It must never reach GitHub. A bot will find it within minutes and drain it.

Anchor's .gitignore covers target/deploy/*.json. If you copy a keypair anywhere else in the repo, add that path yourself. Never reuse this key on mainnet.

Get devnet SOL from the faucet

Do this now, at the start. Four steps:

  1. Go to faucet.solana.com.
  2. Sign in with GitHub. This unlocks the higher limit of 5 SOL. The faucet works signed out, but gives you less than the checkpoint 8 deploy needs.
  3. Paste in the address that solana address printed.
  4. Confirm it landed.
solana balance

You want to see roughly 5 SOL.

Fund your wallet now, not before the deploy

Faucet requests are rate limited with a cooldown between them.

If you reach checkpoint 8 short of SOL, you may be waiting hours to top up. Get your 5 SOL at the start and the rest of the guide never blocks.

If GitHub sign-in is refused The faucet verifies GitHub accounts, and very new accounts are occasionally refused. Post your address in the course Discord and a TA will send you devnet SOL directly.
05
Transaction lifecycle

Send a transaction

Network devnet

When you finish this: a confirmed transaction you can open in the explorer.

Send a transaction yourself, then read back what the network recorded.

This runs on devnet because you need a link other people can open. The whole thing costs 5000 lamports — essentially nothing.

Make somewhere to send it

Create a second keypair to receive the transfer:

solana-keygen new --no-bip39-passphrase --silent -o ~/throwaway.json
solana address -k ~/throwaway.json

It prints the throwaway address.

Send

Transfer 0.1 SOL to it:

solana transfer $(solana address -k ~/throwaway.json) 0.1 --allow-unfunded-recipient

You get back a signature — a long base58 string. Copy it.

That signature is the transaction's identity. It exists because your keypair signed the message; the network did not assign it.

Now ask the network what happened:

solana confirm -v <YOUR_SIGNATURE>

Read what you just did

Open the signature in the explorer. Keep the cluster parameter on the end.

https://explorer.solana.com/tx/<YOUR_SIGNATURE>?cluster=devnet

Match what you see on the page against the terms below:

What you seeWhat it is
SignatureThe transaction ID, produced by signing rather than assigned
Fee payerThe first signer. Pays whether or not the transaction succeeds
Fee5,000 lamports per signature, taken up front
InstructionsOne call to the System Program. Programs do the work; a transaction just carries instructions
Account inputsEvery account the instruction touches, listed in advance and marked writable or read-only
SlotWhich block a validator packed it into
StatusProcessed, then confirmed, then finalized — three levels of "it happened"
The idea behind what you just did

A Solana transaction declares every account it will read or write before it runs.

That one constraint is why the runtime can execute unrelated transactions in parallel. It also explains most of what looks like boilerplate in an Anchor program.

You just sent the simplest possible example of it.

Hint Transaction simulation failed: insufficient funds

Check solana balance and solana config get.

Either the faucet SOL never landed, or you are pointed at a cluster where your wallet is empty.

Same fix for both: confirm the RPC URL, then fund the address that solana address prints.

Optional If devnet's public RPC is throwing errors

The default public devnet RPC is shared by everyone and rate limited. Deploys hit it hardest, sending many transactions in quick succession.

If you see 429 errors or timeouts, get a free devnet endpoint from Helius and point your CLI at it:

solana config set --url <your-helius-devnet-url>

This is a fallback, not a required step. Skip it unless the public RPC is actually failing on you.

06
Scaffold and build

First project

Network localnet — no SOL needed

When you finish this: a generated Anchor project that builds and passes its test.

Anchor generates a working program, a test, and the config that ties them together.

Everything here runs on your own machine. anchor test handles the network itself, so there is no faucet and no SOL involved.

Do this somewhere sensible — on WSL, inside your Linux home directory:

mkdir -p ~/solana && cd ~/solana
anchor init hello_solana
cd hello_solana

What it made

PathWhat it holdsYou edit it?
programs/hello_solana/src/lib.rsThe on-chain programConstantly
tests/hello_solana.tsTypeScript tests that call itConstantly
Anchor.tomlCluster, wallet, program IDsSometimes
target/deploy/Compiled .so and the program keypairNever by hand
target/idl/Generated interface the client readsNever by hand

Open lib.rs and read it before building. It is about fifteen lines: a program ID, one instruction, one log.

The instruction takes a Context listing its accounts — the same up-front account declaration you saw in the explorer at checkpoint 5. Everything you write this term is a variation on that shape.

Build it

Compile the program to SBF bytecode:

anchor build

Expect no output for a long time. That is normal.

The first build takes 5 to 15 minutes It compiles the entire dependency tree from source. Later builds take seconds. Do not cancel it just because nothing is printing.

Building also generates a keypair for your program. Its public key is the program ID.

That ID appears in two text files as well, and they start out disagreeing with the keypair. Sync them:

anchor keys sync
anchor keys list

Both should now print the same program ID.

Hint Why a program has its own keypair

A program on Solana lives in an account like everything else, and that account needs an address. anchor build generates one at target/deploy/hello_solana-keypair.json. The address is baked into your compiled binary through the declare_id! macro, so if lib.rs claims one ID and the deployed account sits at another, every instruction fails with DeclaredProgramIdMismatch.

anchor keys sync rewrites declare_id! and Anchor.toml to match the keypair. Run it after your first build and any time you clone someone else's repo.

Test it

Build, deploy locally, and run the TypeScript tests:

anchor test

You should see one passing test and a transaction signature.

That single command started a disposable network on your machine, deployed to it, ran the tests, then tore the network down. You never start or stop anything yourself.

Target output One passing test means Rust, the Solana CLI, Anchor, and Node all worked together. That is the whole point of this guide.
Optional · 5 min See the validator that anchor test hides

anchor test starts and stops a local validator for you, so you never see one. Run it yourself once to see what is actually happening, and to meet solana logs — the real debugging tool for Solana work.

Start a validator in a second terminal and leave it running:

solana-test-validator          # leave this running
solana config set --url localhost
solana airdrop 100
solana balance

100 SOL, instantly. No GitHub sign-in, no cooldown, no faucet page. Compare that to what you just went through on devnet.

Now open a third terminal and watch the network:

solana logs

Every msg! your program prints shows up here live. This is how you debug a program that is misbehaving.

Clean up — not optional

Point your CLI back at devnet and stop the validator:

solana config set --url devnet
pkill -f solana-test-validator
Skip the cleanup and checkpoint 8 breaks

A validator left running holds port 8899.

The next anchor test then fails with a port-in-use error that looks nothing like its actual cause, and you will lose time hunting the wrong problem.

07
Program derived addresses

Derive a PDA

Network localnet — nothing to fund

When you finish this: a PDA you derived yourself, and proof that deriving is not creating.

A PDA is an address computed from a program ID plus some seeds. It has no private key, which is exactly why programs use it to own state.

Deriving one is pure local maths. No network, no SOL, nothing to fund.

In your hello_solana directory, create pda.js:

const { PublicKey } = require("@coral-xyz/anchor").web3;

const programId = new PublicKey(process.argv[2]);
const seed = process.argv[3] ?? "counter";

const [pda, bump] = PublicKey.findProgramAddressSync(
  [Buffer.from(seed)],
  programId
);

console.log("program", programId.toBase58());
console.log("seed   ", seed);
console.log("pda    ", pda.toBase58());
console.log("bump   ", bump);

Run it with your own program ID from anchor keys list:

node pda.js <YOUR_PROGRAM_ID> counter

Three things to try

  1. Run it twice with the same seed. Same address, every time, on every machine. Nothing was stored anywhere — the address is computed.
  2. Change the seed to vault. Completely different address, from the same program. This is how one program keeps thousands of separate accounts without tracking a single keypair.
  3. Look up the address you derived. It does not exist:
solana account <THE_PDA>   # Error: AccountNotFound
Deriving is not creating

You just computed an address that nobody owns and nothing occupies.

Making it a real account takes a transaction where the program allocates space and pays rent — a one-off deposit for storing data on chain, refunded when the account closes.

In Anchor that becomes the seeds and bump constraints on an init account. The address existed before the account did.

Hint What the bump is for

Roughly half of all seed-and-program-ID combinations land on the Ed25519 curve, meaning a private key could exist for them — useless for a program-owned address. So the derivation appends one extra byte, the bump, and counts down from 255 until the result falls off the curve.

findProgramAddressSync returns the first value that works. That one is called the canonical bump — the bump everyone agrees to use for a given set of seeds.

Programs should always use it. A program that accepts any bump has effectively created several valid addresses for the same seeds, which is a real class of exploit.

Hint Cannot find module '@coral-xyz/anchor'

You are outside the project directory, or dependencies never installed. From ~/solana/hello_solana, run yarn install and try again.

08
A real network

Deploy to devnet

Network devnet — this is the expensive step

When you finish this: your program live on devnet, visible in the explorer.

Same program as checkpoint 6, but a network you do not control. It costs real devnet SOL and takes a minute rather than a second.

Follow these six steps in order. Do not skip step 4.

1 · Check where you are and what you have

solana config get       # RPC URL must say devnet
solana balance          # need at least 3 SOL

Short on SOL? Go back to checkpoint 4 and use the faucet before you continue.

2 · Point Anchor at devnet

Edit Anchor.toml:

[provider]
cluster = "devnet"
wallet = "~/.config/solana/id.json"

3 · Build

anchor build

This should take seconds — you already built once.

4 · Preview the cost before you spend it

Ask what storing the compiled program will cost:

solana rent $(wc -c < target/deploy/hello_solana.so)

Expect a figure in the region of 2 to 3 SOL for a small Anchor program.

Two things make it that high. Solana allocates roughly double your binary size, leaving room to upgrade the program later.

The deploy also creates buffer accounts — temporary accounts that hold your program's bytes while they upload. They cost SOL too.

5 · Deploy

anchor deploy

It prints your program ID when it succeeds.

6 · If the deploy failed, run this before retrying

solana program close --buffers
Do not just run anchor deploy again

A failed deploy leaves buffer accounts holding your SOL.

Retry without closing them and you will run out of SOL with nothing deployed — and then you are waiting on the faucet cooldown.

Close the buffers, check solana balance, then retry.

See it on the network

Open your program ID in the explorer, keeping the cluster on the URL:

https://explorer.solana.com/address/<PROGRAM_ID>?cluster=devnet
solana program show <PROGRAM_ID>

Your program is now an account on a public network, owned by the BPF loader, holding your compiled bytecode. Same account model as everything else you have touched today.

Forgetting ?cluster=devnet

This is the single most common source of confusion here. Without it, the explorer looks on mainnet, finds nothing, and says the account does not exist.

Your deploy was fine. This costs people about twenty minutes each, once.

Clean up when you are done

Close the program to reclaim most of the SOL:

solana program close <PROGRAM_ID> --bypass-warning
solana program close --buffers   # reclaims leftovers from failed deploys

Have a look at it in the explorer first — closing is irreversible.

Optional If devnet's public RPC is throwing errors

Deploys hit the shared public RPC hard, sending many transactions in quick succession. 429 errors and timeouts here are common.

If that happens, get a free devnet endpoint from Helius and point your CLI at it, then retry from step 1:

solana config set --url <your-helius-devnet-url>

Optional fallback. Only bother if the public RPC is failing on you.

09
Wrap up

Check your work

When you finish this: confidence that every piece actually works.

Run through these five yourself before you close the tab:

  1. The verify script below runs clean.
  2. Your anchor test run shows the test passing.
  3. Your transfer signature from checkpoint 5 opens in the explorer.
  4. Your devnet program ID opens in the explorer, with ?cluster=devnet.
  5. You can say in a couple of sentences what broke and how you fixed it. If nothing broke, say why the PDA in checkpoint 7 had no account behind it.
Point five is the one that matters The install is worth nothing on its own — a script did most of it. What sticks is being able to describe a failure precisely enough for another person to act on it. Write yours down somewhere while it is fresh.
V
Copy this whole block

Verify script

Paste this into your terminal. It prints one line per tool, marking each present or missing, then shows your current cluster and wallet. Run it before asking for help, and paste the output with your question.

#!/usr/bin/env bash
# solana-doctor — checks the toolchain for Solana Fall School

for t in rustc cargo solana anchor avm node yarn; do
  if command -v "$t" >/dev/null 2>&1; then
    printf 'ok   %-7s %s\n' "$t" "$("$t" --version 2>/dev/null | head -1)"
  else
    printf 'MISS %-7s not on PATH\n' "$t"
  fi
done

echo
solana config get 2>/dev/null | grep -E 'RPC URL|Keypair Path'
echo "address: $(solana address 2>/dev/null || echo 'no keypair yet')"
echo "balance: $(solana balance 2>/dev/null || echo 'unreachable')"

Healthy output has seven ok lines, an RPC URL pointing at devnet, and a balance. Any MISS line names the tool to reinstall from checkpoint 2 — and only that tool.

Optional Keep it as a command

Save it once and call it by name whenever something feels off:

mkdir -p ~/bin
# paste the script into ~/bin/solana-doctor, then:
chmod +x ~/bin/solana-doctor
echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
solana-doctor
?
When it breaks

Troubleshooting

Ranked by how often it actually happens in a room of forty people.

Error Deploy failed and now I have no SOL

Buffer accounts from the failed deploy are holding it. Close them and check what came back:

solana program close --buffers
solana balance

Do this before you retry the deploy, every time. Retrying without it is how people end up at zero with nothing deployed.

Error Faucet says rate limited

There is a cooldown between requests. Waiting it out is the only real fix.

This is why checkpoint 4 tells you to fund your wallet at the start. If you are blocked and up against the deadline, post your address in the course Discord.

Error GitHub sign-in refused at the faucet

The faucet verifies GitHub accounts, and very new accounts sometimes fail that check.

Ask a TA in the course Discord to send devnet SOL to your address directly. Post the output of solana address.

Error 429 or timeout errors during deploy

The public devnet RPC is shared and overloaded. A deploy sends many transactions quickly, so it hits the limit before anything else does.

Switch to a free Helius devnet endpoint and retry:

solana config set --url <your-helius-devnet-url>

Check solana program close --buffers first if the deploy already failed once.

Error command not found: solana / anchor / avm

PATH, essentially always. Either you have not opened a new terminal since installing, or the export line went into the wrong shell profile. Check with echo $SHELL, then append the export to .bashrc or .zshrc — see the hint under checkpoint 2.

On macOS, also check you do not have a Homebrew Rust shadowing the rustup one: which -a rustc should show only the ~/.cargo/bin path.

Error could not exec the linker cc — Permission denied (os error 13)

Missing build dependencies on Linux or WSL, despite what the message implies about permissions. Run the apt-get install block from checkpoint 0, then retry the Anchor install. Do not prefix cargo or avm with sudo — that creates root-owned files in your cargo directory and a second, worse problem.

Error No such file or directory (os error 2)

Anchor tried to spawn a binary and will not say which. Ask it directly — whichever comes back empty is your answer:

which rustc cargo solana anchor node yarn cargo-build-sbf

During anchor test specifically, this usually means Node or Yarn is missing, since the test template is TypeScript.

Error anchor test fails with a port already in use

Something is already holding port 8899, so the new validator cannot bind.

Two causes. Either a previous run crashed and left its validator behind, or you started solana-test-validator yourself — for example in the optional detour under checkpoint 6 — and never stopped it.

Same fix for both:

pkill -f solana-test-validator
anchor test
Error DeclaredProgramIdMismatch

The ID in declare_id! does not match the keypair the program was deployed under. Standard after a fresh clone or a target/ wipe:

anchor keys sync
anchor build
anchor deploy
Error Account not found in the explorer

You are looking at mainnet. Append ?cluster=devnet to the URL, or pick the cluster in the explorer's top-right dropdown. Anything deployed by anchor test will not appear there at all — that network only existed for the duration of the command.

Error solana airdrop fails / 429 Too Many Requests

solana airdrop goes through the public devnet RPC, which rate limits by IP. A lecture hall on one wifi network hits that limit constantly.

Use faucet.solana.com signed in with GitHub instead, as checkpoint 4 describes. Ask once rather than repeatedly.

On localnet none of this applies — solana airdrop 100 works instantly and as often as you like.

Error Builds are unbearably slow on Windows

Your project is on /mnt/c. Every file read crosses from WSL to the Windows filesystem, which is roughly an order of magnitude slower. Move it:

cp -r /mnt/c/Users/you/hello_solana ~/
cd ~/hello_solana && anchor build
Error lock file version 4 requires -Znext-lockfile-bump

Your Rust is older than the lockfile the project's dependencies expect. rustup update stable fixes it. The general shape of this class of error is a dependency requiring a newer toolchain than you have — read the version it names before editing anything, and use cargo tree -i <crate> to find which dependency pulled it in.

Guide 01 · never commit a keypair · commands verified against solana.com/docs, August 2026