Docs

Troubleshooting

Fix the most common Proa setup, registry, template, component, island, routing, and CI failures.

Open Markdown

Start with the fastest checks. They separate environment problems from template and runtime problems:

proa --help
cargo check
proa fmt --check --verify src
proa lint --min-severity info src
proa site check

If you are working from the Proa repository instead of an installed CLI, use the Cargo wrapper:

cargo run -p proa-cli --bin proa -- fmt --check --verify src
cargo run -p proa-cli --bin proa -- lint --min-severity info src

proa: command not found

Right after an install, the cause is PATH. The installer appends an export PATH line to every shell profile it finds (~/.bashrc, ~/.bash_profile, ~/.zshrc, ~/.profile, and ~/.config/fish/config.fish), and the shell you are already in never rereads those files. Open a new terminal, or add the directory to the current shell by hand:

export PATH="$HOME/.proa/bin:$PATH"

Confirm that the binaries landed where you expect:

ls "$HOME/.proa/bin"
"$HOME/.proa/bin/proa" --version

On Windows, the installer writes the directory into your user PATH and into the terminal it ran in, so that terminal can run proa right away. Every other process keeps the PATH it started with, so restart any other terminal or editor before running proa --version there. Check the persisted value with:

[Environment]::GetEnvironmentVariable("Path", "User")

The installer refuses to rewrite a user PATH that contains %VAR% references, because rewriting one would freeze today's expansion. It warns and prints the line to add when it finds one.

If you ran cargo install or the installer fell back to a source build, the binaries live in ~/.cargo/bin instead. Point the same export line at that directory.

If you passed PROA_NO_MODIFY_PATH or --no-modify-path, the installer left your profiles, and the Windows user PATH, alone by design, and printed the line to add. Add it yourself, or run the installer again without that flag.

Every run writes a log that lists which profile files the installer examined, which it changed, and which already had the line. The installer prints the path as it exits, and it looks like /tmp/proa-install-20260813T221500Z-1234.log (under %TEMP% on Windows). Read that when the PATH change did not land where you expected, and attach it if you report the problem.

When you are developing inside this repository, run the CLI through Cargo instead:

cargo run -p proa-cli --bin proa -- --help

Then use that same prefix for later commands. See Install Proa and the CLI reference.

The Installer Cannot Reach The Download Host

The installer fetches release archives from https://proa.so/downloads/cli, the value of PROA_DOWNLOAD_BASE. A connection failure or a 503 from that host stops the download before there is anything to verify.

A 503 means the release host behind the bridge is unavailable or rate limited. The response carries Retry-After: 30, so wait half a minute and run the installer again. Check the endpoint yourself:

curl --proto '=https' --tlsv1.2 -sS -i https://proa.so/downloads/cli/latest.json

A 200 with a version field means the host is healthy and the problem is between you and it, usually a proxy or a DNS resolver. If the failure persists, build the CLI from source instead:

curl -fsSL https://proa.so/install.sh | PROA_BUILD_FROM_SOURCE=1 sh

Or point the installer at another host that serves the same file names:

curl -fsSL https://proa.so/install.sh | PROA_DOWNLOAD_BASE=https://mirror.example/downloads/cli sh

PROA_REPO does not help here. It selects the repository the source build compiles from, not the host archives come from.

The installer log records the request and what came back. Its path is printed as the installer exits.

No Release Is Published Yet

https://proa.so/downloads/cli/latest.json answers 404 when no proa-cli release exists. The installer reads that as "there is no version to install" rather than a failure, and compiles the CLI with Cargo instead. The log names the outcome, and the run ends with a working proa, just built rather than downloaded.

The source build puts proa and cargo-proa in ~/.cargo/bin, not ~/.proa/bin, so look there when the shell cannot find the binary afterwards.

Pinning PROA_VERSION does not change this. A version with no published archives answers 404 on the asset URL too.

Checksum Verification Failed

The installer compares the downloaded archive against the SHA256SUMS file for that release. A mismatch stops the install before the installer unpacks anything, and it deletes the temporary directory it downloaded into, so nothing was installed and no unpacked binary was left behind.

A truncated download, a proxy that rewrote the response, or a stale cache all produce this. Run the installer again first. If the mismatch survives a retry, fetch both files and check them yourself:

VERSION=0.1.0
TARGET=x86_64-unknown-linux-gnu
BASE="https://proa.so/downloads/cli/$VERSION"
curl --proto '=https' --tlsv1.2 -fLO "$BASE/proa-cli-$VERSION-$TARGET.tar.gz"
curl --proto '=https' --tlsv1.2 -fLO "$BASE/proa-cli-$VERSION-SHA256SUMS"
shasum -a 256 --ignore-missing -c "proa-cli-$VERSION-SHA256SUMS"

Use sha256sum --ignore-missing -c on Linux. A clean download on a different network settles the question: if it verifies there, your first download passed through something that changed it. If it fails there too, do not install the archive. Open an issue with the version, the target triple, and the digest you computed, and attach the installer log. It records the URL it fetched, the expected hash, and the hash it computed. Its path is printed as the installer exits.

To keep moving in the meantime, build the CLI from source instead:

curl -fsSL https://proa.so/install.sh | PROA_BUILD_FROM_SOURCE=1 sh

No Prebuilt Binary For This Platform

For now, Proa publishes one native release binary: x86_64-unknown-linux-gnu, built on Ubuntu 24.04. It supports 64-bit Ubuntu 24.04+ and other glibc 2.39+ Linux systems. On anything else, including older Ubuntu releases, ARM Linux, Alpine and other musl distributions, macOS, Windows, FreeBSD, and 32-bit hosts, the installer reports that it found no matching asset and compiles the CLI with Cargo instead. While the repository is private, that fallback requires GitHub access:

CARGO_NET_GIT_FETCH_WITH_CLI=true \
  cargo install --git https://github.com/proa-labs/proa --locked proa-cli

No private Cargo index or Cargo token is required. The installer enables CARGO_NET_GIT_FETCH_WITH_CLI=true when Git is available so your Git credential helper and proxy settings apply. For private repository access, configure your GitHub credentials before running the source installer.

That build takes several minutes and needs Rust 1.93.0 or newer plus a C toolchain. On Alpine, install the toolchain first:

apk add build-base

Alpine's packaged Rust lags the 1.93.0 minimum on some releases. Run rustc --version, and install the toolchain with rustup when the packaged one is older. The installer does not install Rust for you: it stops and prints the rustup command instead. And when the only downloader on the system is BusyBox wget, which cannot enforce HTTPS-only transfers, the installer stops and asks for curl before downloading anything:

apk add curl

The source build puts proa and cargo-proa in ~/.cargo/bin, not ~/.proa/bin, so check that directory when the shell cannot find the binary afterwards.

When the fallback surprises you on a platform that does have a published binary, read the installer log. It records the raw uname output, the libc it detected and how, the target triple it resolved, and the asset lookup that came back empty. Attach it if you report the detection as wrong.

Cargo Cannot Download Proa Crates

Generated projects declare Proa crates as git dependencies on https://github.com/Proa-Labs/proa.git. Confirm that your project has a .cargo/config.toml that fetches them with the Git CLI:

[net]
git-fetch-with-cli = true

git-fetch-with-cli makes Cargo use your Git credential helper and proxy settings. No [registries.proa] configuration is needed. If an existing project still reports a missing proa index, update its Proa Git dependencies with cargo update; its lockfile may pin a commit from before this migration. Use the same Git URL and revision for all Proa dependencies.

While the repository is private, the git fetch needs GitHub access, on your machine and in CI. See Installation and CI / GitHub Actions.

The Page Builds But Styles Are Missing

Generated Tailwind sites write public/styles.css. If the page renders unstyled, rebuild the stylesheet with the same command the proa dev / proa build asset step runs:

tailwindcss -i styles/input.css -o public/styles.css

If tailwindcss is not on PATH, install Tailwind CSS CLI v4 with the Proa installer (curl -fsSL https://proa.so/install.sh | sh -s -- --tailwind-only) or with Homebrew (brew install tailwindcss).

Use --no-tailwind when scaffolding if you want to bring your own stylesheet pipeline.

html_sync! Or html! Does Not Parse

Run the formatter with structural verification first:

proa fmt --check --verify src

Common causes:

SymptomFix
A void element has childrenUse a self-closing element such as <input ... />.
Attribute syntax is split by invalid tokensKeep names like data-state and aria-label as one attribute token.
Dynamic text appears without bracesUse {value} for Rust expressions and quoted text for static strings.
A generated macro body has odd spacingRun proa fmt src, then cargo fmt --all.

See The html! Macro and Format, Lint, And Check.

A Component Has Trait Errors

Most page and component render paths should implement WebRenderSync. Keep the implementation generic over the data loader; the output defaults to the owned RenderBuffer:

use proa_core::{DataLoader, WebContext, WebRenderSync, WriteError};

impl<L: DataLoader> WebRenderSync<L> for MyComponent {
    fn render(self, cx: &mut WebContext<L>) -> Result<(), WriteError> {
        // ...
        Ok(())
    }
}

If you place a sync component inside an async html! tree, wrap it with proa_core::to_async(...). If the component awaits data or uses async loaders, implement WebRender and render with html!. See Render traits.

Classes Disappear Or ClassList Fails

ClassList<N> has fixed capacity. Count every segment you add, including optional classes:

let classes = ClassList::<4>::new()
    .add(BASE)
    .add(size.classes())
    .add(variant.classes())
    .add_opt(self.class);

Prefer increasing the capacity over building a String in the render path. See Class composition.

An Island Renders But Clicks Do Nothing

Check the browser network panel first. The page should load the rsjs runtime and the island chunk without 404s.

Then confirm:

See RSJS.

A New Route Returns 404

Run the site checks:

proa site routes
proa site check

Confirm that the route is registered in the router, the page module is exported, and generated metadata points at the same path. See Framework routing and Site commands.

CI Fails But Local Checks Pass

Make CI run the same commands as local development:

cargo fmt --all --check
cargo check
proa check src

If CI fails before compilation, check GitHub access for the Proa git dependencies first. While the repository is private, every Cargo invocation that resolves dependencies needs credentials for it, including cargo check, cargo test, and cargo clippy.

For GitHub annotations, run:

proa lint --github --changed --base origin/main

Git selection replaces the path argument: --changed and --base cannot be combined with explicit paths.

See CI / GitHub Actions.

Still Stuck

Capture the exact failing command and a machine-readable diagnostic:

proa lint --json --min-severity info src
proa chunks --json src

Include the failing route, the rendered HTML snippet if a browser page looks wrong, and the first compiler or CLI diagnostic that points at your code.

For an install that failed, attach the installer log instead. The installer prints its path on the way out, on success and on failure, and PROA_LOG=/path/to/file writes it where you choose. Rerun with PROA_VERBOSE=1 to see the same detail in the terminal while you work.

Search

Type at least 2 characters