clockworklabs/SpacetimeDB · error · anyhow::Error

Could not find StdbModule.csproj at

Error message

Could not find StdbModule.csproj at {}

What it means

With --native-aot, init post-processes the C# module project expecting a file literally named StdbModule.csproj in the module directory. If generation produced a differently named csproj (renamed/absent) the AOT step bails before editing.

Solutions

  1. Regenerate the project (`spacetime init --lang csharp`) and keep the default StdbModule.csproj name through the AOT step
  2. If you must rename, rename after init completes, or update the forked template to emit StdbModule.csproj
  3. Verify `spacetimedb/StdbModule.csproj` exists before rerunning with --native-aot
Defensive patterns

Strategy: validation

Validate before calling

# verify the expected file exists before rerunning init with AOT
[ -f spacetimedb/StdbModule.csproj ] && spacetime init . --server-only --native-aot || echo 'missing StdbModule.csproj'

Prevention

When it happens

Trigger: --native-aot on a C# project whose csproj was renamed before init finished; a custom/forked template using a different csproj filename; running the AOT step against a non-C# or half-generated project layout.

Common situations: Team conventions renaming the module csproj; forked templates; scripts rerunning init steps out of order.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@fdd647dfac (2026-08-20). Data as JSON: /api/errors/833ad33633103503. Report an issue: GitHub.

Appendix: source

Thrown at crates/cli/src/subcommands/init.rs:1942

        .unwrap_or(false)
}

/// Adds NativeAOT-LLVM project configuration to an existing C# .csproj file and creates NuGet.Config.
///
/// The configuration differs depending on the target .NET version:
///
/// **.NET 8 AOT** (`--native-aot`): Keeps `net8.0` TFM and adds explicit ILCompiler.LLVM 8.0.0-*
/// package references, gated on `EXPERIMENTAL_WASM_AOT=1`.
///
/// **.NET 10 AOT**: Replaces the TFM with `net10.0` directly (no conditional needed since the
/// project is definitively targeting .NET 10). ILCompiler.LLVM refs are provided transitively
/// by the SpacetimeDB.Runtime NuGet package.
///
/// Both paths need a NuGet.Config with the dotnet-experimental feed for ILCompiler.LLVM resolution.
fn add_native_aot_packages_to_csproj(project_path: &Path, dotnet_major: Option<u8>) -> anyhow::Result<()> {
    let csproj_path = project_path.join("StdbModule.csproj");
    if !csproj_path.exists() {
        anyhow::bail!("Could not find StdbModule.csproj at {}", csproj_path.display());
    }

    let content = std::fs::read_to_string(&csproj_path)?;

    let new_content = if dotnet_major == Some(8) {
        let has_net8_native_aot_refs =
            csproj_has_package_reference(&content, "Microsoft.DotNet.ILCompiler.LLVM", "8.0.0-*")
                && csproj_has_package_reference(
                    &content,
                    "runtime.$(NETCoreSdkPortableRuntimeIdentifier).Microsoft.DotNet.ILCompiler.LLVM",
                    "8.0.0-*",
                );

        if has_net8_native_aot_refs {
            content
        } else {
            // .NET 8 AOT: keep net8.0 TFM, add explicit ILCompiler.LLVM package references.
            let native_aot_config = r#"

View on GitHub (pinned to fdd647dfac)