zeroclaw-labs/zeroclaw · error

Nucleo firmware not found at {}. Run from zeroclaw repo root

Error message

Nucleo firmware not found at {}. Run from zeroclaw repo root.

What it means

flash_nucleo_firmware locates the firmware at <CARGO_MANIFEST_DIR>/firmware/nucleo, where CARGO_MANIFEST_DIR is baked in at compile time from the zeroclaw-hardware crate. This bail fires when that directory has no Cargo.toml. Despite the message saying 'Run from zeroclaw repo root', the path does not depend on the current working directory — changing directories cannot fix it.

Source

Thrown at crates/zeroclaw-hardware/src/peripherals/nucleo_flash.rs:35

        .map(|o| o.status.success())
        .unwrap_or(false)
}

/// Flash ZeroClaw Nucleo firmware. Builds from firmware/nucleo.
pub fn flash_nucleo_firmware() -> Result<()> {
    if !probe_rs_available() {
        anyhow::bail!(
            "probe-rs not found. Install it:\n  cargo install probe-rs-tools --locked\n\n\
             Or: curl -LsSf https://github.com/probe-rs/probe-rs/releases/latest/download/probe-rs-tools-installer.sh | sh\n\n\
             Connect Nucleo via USB (ST-Link). Then run this command again."
        );
    }

    // CARGO_MANIFEST_DIR = repo root (zeroclaw's Cargo.toml)
    let repo_root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    let firmware_dir = repo_root.join("firmware").join("nucleo");
    if !firmware_dir.join("Cargo.toml").exists() {
        anyhow::bail!(
            "Nucleo firmware not found at {}. Run from zeroclaw repo root.",
            firmware_dir.display()
        );
    }

    println!("Building ZeroClaw Nucleo firmware...");
    let build = Command::new("cargo")
        .args(["build", "--release", "--target", TARGET])
        .current_dir(&firmware_dir)
        .output()
        .context("cargo build failed")?;

    if !build.status.success() {
        let stderr = String::from_utf8_lossy(&build.stderr);
        anyhow::bail!("Build failed:\n{}", stderr);
    }

    let elf_path = firmware_dir

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Use a full git clone of the zeroclaw repo so firmware/nucleo sits next to crates/zeroclaw-hardware, and run the flash from that checkout
  2. Verify the path printed in the error contains Cargo.toml; if not, restore the firmware/nucleo directory
  3. Rebuild zeroclaw inside the full checkout so CARGO_MANIFEST_DIR resolves to it
Defensive patterns

Strategy: validation

Validate before calling

let firmware = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
    .join("firmware").join("nucleo");
if !firmware.join("Cargo.toml").exists() {
    anyhow::bail!("full zeroclaw checkout required: {} missing", firmware.display());
}
flash_nucleo_firmware()?;

Prevention

When it happens

Trigger: The zeroclaw binary was built from a source tree lacking firmware/nucleo (sparse checkout, packaged crate build), so the compiled-in absolute path points at a directory that does not exist on this machine.

Common situations: Using a prebuilt/released zeroclaw binary and expecting it to flash firmware; partial clones that exclude the firmware directory; moving or deleting the repo after building.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/87e9cdfc58a3ac0e. Report an issue: GitHub.