a-b-street/abstreet · error

Couldn't find the executable. Is it built?

Error message

Couldn't find the {} executable. Is it built?

What it means

find_exe locates an external executable that map_gui tools depend on, checking configured paths and the current binary's directory. If the command is found as a matching path but isn't a file, or no matching path is found at all, it panics with "Couldn't find the {cmd} executable. Is it built?". The message hints that the repo's own companion binary (e.g. updater, release helper) hasn't been compiled yet.

Solutions

  1. Build the missing executable (usually `cargo build --release` for the whole workspace so sibling binaries exist).
  2. Run the app from the directory containing the built binaries, or place the executable on PATH / in the expected search location.
  3. Ensure the built binary matches your platform/target triple (no cross-compile mismatch).
  4. If packaging, bundle the helper executables alongside the main binary.

Example fix

// before
./target/release/map_gui --release-tool   # updater binary never built
// after
cargo build --release --workspace
./target/release/map_gui --release-tool
Defensive patterns

Strategy: validation

Validate before calling

let exe = "updater";
assert!(which::which(exe).is_ok() || std::path::Path::new("target/release").join(exe).is_file(),
        "{} not built; run cargo build --release --workspace", exe);

Try / catch

// Panics uncatchably; probe for the executable before invoking the tool:
if !std::path::Path::new("target/release/updater").is_file() {
    eprintln!("helper binary missing; skipping tool");
    return;
}

Prevention

When it happens

Trigger: Invoking a map_gui tool (release/upload/change-detection features) that calls find_exe(cmd) when the companion binary hasn't been built, was built for the wrong target, or sits outside the searched directories.

Common situations: Running only `cargo build` for one crate so sibling binaries in the workspace never got compiled; running the app outside target/release so relative lookup paths break; cross-compiling so the expected target-triple directory differs; tools invoked from a packaged binary without bundling the helper executables.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13). Data as JSON: /api/errors/25d99c8eeeebfea8. Report an issue: GitHub.

Appendix: source

Thrown at map_gui/src/tools/mod.rs:419

        // Apparently std::path on Windows doesn't do any of this correction. We could build up a
        // PathBuf properly, I guess
        let path = if cfg!(windows) {
            format!("{}/{}.exe", dir, cmd).replace("/", "\\")
        } else {
            format!("{}/{}", dir, cmd)
        };
        if let Ok(metadata) = fs_err::metadata(&path) {
            if metadata.is_file() {
                return path;
            } else {
                debug!(
                    "found matching path: {}/{} but it's not a file.",
                    &path, cmd
                );
            }
        }
    }
    panic!("Couldn't find the {} executable. Is it built?", cmd);
}

/// A button to change maps, with default keybindings
pub fn change_map_btn(ctx: &EventCtx, app: &dyn AppLike) -> Widget {
    ctx.style()
        .btn_popup_icon_text(
            "system/assets/tools/map.svg",
            nice_map_name(app.map().get_name()),
        )
        .hotkey(lctrl(Key::L))
        .build_widget(ctx, "change map")
}

/// A button to return to the title screen
pub fn home_btn(ctx: &EventCtx) -> Widget {
    ctx.style()
        .btn_plain
        .btn()

View on GitHub (pinned to 0964f29315)