Skip to content

Windows: node_binary::find cargo-target-dir fallback ignores .exe, forcing unnecessary cargo install for dora record/dora replay #3145

Description

@phil-opp

Note: This issue was created by a scheduled automated Claude check that randomly reviews a component of the codebase for correctness issues. Please verify before acting on it.

Summary

In binaries/cli/src/command/node_binary.rs, the search() helper's cargo-target-directory fallback probes only the bare binary name and never <name>.exe. On Windows, cargo build produces target/{debug,release}/<name>.exe, so this branch can never locate a binary there. The result is that dora record / dora replay fall through to a slow cargo install on Windows even after a successful workspace cargo build.

Location

binaries/cli/src/command/node_binary.rs:75-80

// Check cargo target directory (development)
let cargo_target = std::env::var("CARGO_TARGET_DIR")
    .map(PathBuf::from)
    .unwrap_or_else(|_| PathBuf::from("target"));
for profile in ["debug", "release"] {
    let candidate = cargo_target.join(profile).join(binary_name);   // <-- no `.exe`
    if candidate.exists() {
        return dunce::canonicalize(candidate).ok();
    }
}

Why this is a bug

The exe-adjacent search directly above (lines 57-63) already special-cases Windows and checks both binary_name and format!("{binary_name}.exe"):

#[cfg(target_os = "windows")]
{
    let candidate = dir.join(format!("{binary_name}.exe"));
    if candidate.exists() {
        return Some(candidate);
    }
}

The cargo-target-dir loop was not given the same treatment, so the two lookup paths are inconsistent. On Windows the target-dir branch is effectively dead — candidate.exists() is always false for a real cargo-built binary.

Impact

find() is called by dora record and dora replay to locate dora-record-node / dora-replay-node:

  • binaries/cli/src/command/record.rs:519node_binary::find("dora-record-node", "dora-record-node")
  • binaries/cli/src/command/replay.rs:389node_binary::find("dora-replay-node", "dora-replay-node")

Trigger scenario (Windows), where dora.exe is installed standalone (e.g. ~/.cargo/bin/dora.exe, not inside target/debug) and the node crate was built into ./target/debug/:

  1. search() → exe-adjacent: dora.exe's directory has no dora-record-node[.exe] → miss.
  2. PATH via which: the freshly built binary in target/debug/ is not on PATH → miss.
  3. target-dir loop: checks target/debug/dora-record-node (no .exe) → miss → returns None.

So find() reports "not found", runs cargo build -p dora-record-node (which succeeds and writes target/debug/dora-record-node.exe), then re-search() still cannot find the .exe it just built via the target-dir loop, and the code falls through to cargo install at line 29 — an unnecessary, slow reinstall even though the workspace build already produced the binary.

Suggested fix

Mirror the exe-adjacent block in the target-dir loop, e.g. also probe <name>.exe on Windows:

for profile in ["debug", "release"] {
    let candidate = cargo_target.join(profile).join(binary_name);
    if candidate.exists() {
        return dunce::canonicalize(candidate).ok();
    }
    #[cfg(target_os = "windows")]
    {
        let candidate = cargo_target.join(profile).join(format!("{binary_name}.exe"));
        if candidate.exists() {
            return dunce::canonicalize(candidate).ok();
        }
    }
}

(Using std::env::consts::EXE_SUFFIX would be an even cleaner cross-platform way to append the suffix in both this loop and the exe-adjacent block.)

Severity

Windows-only; degraded behavior (unnecessary rebuild/reinstall + confusing "not found in workspace, installing…" message), not a crash or data loss.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions