clockworklabs/SpacetimeDB · error · anyhow::Error
Could not find StdbModule.csproj at {}
Error message
Could not find StdbModule.csproj at {} What it means
The NativeAOT configuration step (add_native_aot_packages_to_csproj) expects StdbModule.csproj at the project root and bails with the full expected path when it is missing (init.rs:1916). It is reached when building/publishing a C# module with native-aot enabled.
Source
Thrown at crates/cli/src/subcommands/init.rs:1916
Ok(())
}
/// 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) {
// .NET 8 AOT: keep net8.0 TFM, add explicit ILCompiler.LLVM package references.
let native_aot_config = r#"
<ItemGroup Condition="'$(EXPERIMENTAL_WASM_AOT)' == '1'">
<PackageReference Include="Microsoft.DotNet.ILCompiler.LLVM" Version="8.0.0-*" />
<PackageReference Include="runtime.$(NETCoreSdkPortableRuntimeIdentifier).Microsoft.DotNet.ILCompiler.LLVM" Version="8.0.0-*" />
</ItemGroup>
"#;
if let Some(pos) = content.rfind("</Project>") {
let (before, after) = content.split_at(pos);
format!("{}{}{}", before.trim_end(), native_aot_config, after)
} else {
anyhow::bail!("Invalid .csproj file: missing </Project> tag");
}View on GitHub (pinned to 524b4487d9)
Solutions
- Run from (or pass --project-path to) the directory that contains StdbModule.csproj
- Rename your csproj back to StdbModule.csproj
- Remove the native-aot setting/flag when building non-C# modules
- Regenerate the module with `spacetime init` to restore the expected layout
Example fix
// before (repo root, no csproj here) spacetime publish --project-path . --native-aot // after spacetime publish --project-path modules/csharp --native-aot
Defensive patterns
Strategy: validation
Validate before calling
test -f "$PROJECT_DIR/StdbModule.csproj" || {
echo "StdbModule.csproj not found in $PROJECT_DIR" >&2; exit 2
}
spacetime publish --project-path "$PROJECT_DIR" --native-aot Type guard
fn is_csharp_module_root(dir: &std::path::Path) -> bool {
dir.join("StdbModule.csproj").is_file()
} Prevention
- Run publish from the module directory or pass an explicit --project-path
- Keep the generated file name StdbModule.csproj
- Disable native-aot in spacetime.json for non-C# targets
When it happens
Trigger: Publishing with --native-aot (or native-aot: true in spacetime.json) from a directory that is not the C# module root, or after StdbModule.csproj was renamed or deleted.
Common situations: Running `spacetime publish` from the repo root instead of the module directory; a spacetime.json with a stale/wrong project-path; renaming the generated csproj; leaving native-aot enabled for a Rust or TypeScript target.
Related errors
- --native-aot is only supported for C# projects (--lang cshar
- Invalid C# template: missing net8.0/net10.0 TargetFrameworks
- Invalid .csproj file: missing </Project> tag
- never types are not yet supported in C# output
- Unsupported --dotnet-version {version}. Supported values: 8,
AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16).
Data as JSON: /api/errors/833ad33633103503.
Report an issue: GitHub.