clockworklabs/SpacetimeDB · error · anyhow::Error

{error}

Error message

{error}

What it means

Same `dotnet --version` probe as the 'dotnet not found' error, but the failure is an OS error whose kind is not NotFound -- the raw io::Error is re-thrown verbatim. This includes permission/exec-format problems spawning dotnet and, via duct, non-zero exits of `dotnet --version` itself (the error string carries dotnet's stderr).

Source

Thrown at crates/cli/src/tasks/csharp.rs:212

    let native_aot_flag = native_aot;

    let project_global_json = find_global_json(project_path);
    let cwd = std::env::current_dir()?;
    let cwd_global_json = find_global_json(&cwd);
    let dotnet_version_result = if project_global_json.is_some() {
        Some(dotnet!("--version").read())
    } else if cwd_global_json.is_some() {
        Some(duct::cmd!("dotnet", "--version").read())
    } else {
        None
    };
    let dotnet_version_str = match dotnet_version_result {
        Some(Ok(v)) => Some(v),
        Some(Err(error)) if error.kind() == std::io::ErrorKind::NotFound => {
            anyhow::bail!("dotnet not found in PATH. Please install .NET SDK 8.0 or 10.0.")
        }
        Some(Err(error)) => anyhow::bail!("{error}"),
        None => None,
    };

    // Resolution order:
    //   1. --dotnet-version CLI flag (explicit user override)
    //   2. global.json-selected SDK, if one applies to the project or current directory
    //   3. Single <TargetFramework> in the project's .csproj
    //   4. .NET 10 default for missing or multi-target project context
    let csproj_tfms = read_tfms_from_csproj(project_path);
    let dotnet_major = dotnet_version_override
        .or_else(|| dotnet_version_str.as_deref().and_then(parse_major_version))
        .or_else(|| csproj_tfms.as_ref().and_then(CsprojTargetFrameworks::single_major))
        .or(Some(10));

    // Determine the build path based on SDK version and --native-aot flag.
    let build_path = match (dotnet_major, native_aot_flag) {
        // .NET 10: always use NativeAOT-LLVM, no flag needed.
        (Some(10), _) => {

View on GitHub (pinned to 9e0d92412f)

Solutions

  1. Run `dotnet --version` yourself in the same directory -- you will see the identical failure the CLI is surfacing.
  2. If it is a global.json pin mismatch, install the pinned SDK or update global.json to one you have.
  3. Fix the underlying cause: reinstall the SDK, ensure the binary is executable and matches your architecture.
  4. If global.json is not needed, delete it -- the version probe is skipped and the SDK is chosen from the csproj or --dotnet-version.

Example fix

// before: global.json pins an SDK you don't have
{"sdk":{"version":"8.0.100"}}
// after: roll forward to whatever 8.0.x is installed
{"sdk":{"version":"8.0.100","rollForward":"latestFeature"}}
Defensive patterns

Strategy: try-catch

Validate before calling

# Pre-flight the exact probe the CLI performs, in the project directory
cd "$PROJECT_DIR" && dotnet --version || { echo "dotnet probe failed; fix SDK/global.json" >&2; exit 1; }
spacetime build

Try / catch

out=$(spacetime build 2>&1); status=$?
if [ $status -ne 0 ]; then
  echo "$out" | tail -5   # the raw io::Error / dotnet stderr is embedded verbatim
  dotnet --version         # reproduce to get the full underlying error
fi

Prevention

When it happens

Trigger: `spacetime build` on a C# project with a global.json where dotnet exists but `dotnet --version` fails: a global.json pinning an SDK version that is not installed (dotnet exits non-zero with NETSDK1056-style errors), a non-executable or wrong-architecture binary, or a corrupt install.

Common situations: Repo-level global.json pinning e.g. 8.0.100 while only SDK 9/10 is installed; dotnet installed for a different CPU arch; sandboxed CI denying exec; partially upgraded SDKs.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@9e0d92412f (2026-08-20). Data as JSON: /api/errors/59b22022342d2f6a. Report an issue: GitHub.