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
- Regenerate the project (`spacetime init --lang csharp`) and keep the default StdbModule.csproj name through the AOT step
- If you must rename, rename after init completes, or update the forked template to emit StdbModule.csproj
- 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
- Keep the module csproj named StdbModule.csproj until init finishes
- Rename or restructure the csproj only after the full init pipeline completes
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
- Invalid .csproj file: missing </Project> tag
- Invalid C# template: missing net8.0/net10.0…
- --native-aot is only supported for C# projects (--lang…
- --dotnet-version is only supported for C# projects (--lang…
- Argument must be a ConnectionId
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)