clockworklabs/SpacetimeDB · error · anyhow::Error
Invalid C# template: missing net8.0/net10.0…
Error message
Invalid C# template: missing net8.0/net10.0 TargetFrameworks property
What it means
While pinning the .NET version, the CLI rewrites the csproj by finding the exact marker `<TargetFrameworks>net8.0;net10.0</TargetFrameworks>` and replacing it with a single `<TargetFramework>net8.0|net10.0</TargetFramework>`. If the embedded C# template's csproj no longer contains that marker (template drift, tampered install, or a modified template in a fork), rewriting fails and init aborts.
Solutions
- Update/reinstall the official CLI so embedded templates match the rewrite logic
- Falling back to the default (no --dotnet-version) lets generation proceed with the multi-target csproj
- If building from source, restore the marker in templates or update the matcher, then rebuild
- Report as a bug if reproducible on an official release
Defensive patterns
Strategy: fallback
Prevention
- Pin a stable official CLI release instead of custom builds for day-to-day init
- Fork maintainers: keep the net8.0;net10.0 TargetFrameworks marker intact when editing templates
When it happens
Trigger: Using --lang csharp with --dotnet-version on a CLI whose embedded template csproj changed shape; forked CLI with edited templates; partially updated install.
Common situations: Template refactors between CLI versions; custom forks that restyle the csproj; corrupted installation.
Related errors
- Could not find StdbModule.csproj at
- --dotnet-version is only supported for C# projects (--lang…
- Invalid .csproj file: missing </Project> tag
- Client template not found
- dotnet not found in PATH. Please install .NET SDK 8.0 or…
AI-assisted analysis of clockworklabs/SpacetimeDB@fdd647dfac (2026-08-20).
Data as JSON: /api/errors/81efe18dc5fe9e32.
Report an issue: GitHub.
Appendix: source
Thrown at crates/cli/src/subcommands/init.rs:1891
_ => unreachable!("unsupported .NET version should have been validated before init"),
}
}
fn csharp_csproj_for_target(content: &str, dotnet_major: u8) -> anyhow::Result<String> {
let target_framework = match dotnet_major {
8 => "net8.0",
10 => "net10.0",
_ => unreachable!("unsupported .NET version should have been validated before init"),
};
let target_framework_property = format!("<TargetFramework>{target_framework}</TargetFramework>");
if content.contains("<TargetFrameworks>net8.0;net10.0</TargetFrameworks>") {
return Ok(content.replace(
"<TargetFrameworks>net8.0;net10.0</TargetFrameworks>",
&target_framework_property,
));
}
anyhow::bail!("Invalid C# template: missing net8.0/net10.0 TargetFrameworks property")
}
fn configure_csharp_project_files(project_path: &Path, dotnet_major: u8) -> anyhow::Result<()> {
let global_json_path = project_path.join("global.json");
std::fs::write(&global_json_path, csharp_global_json(dotnet_major))?;
let csproj_path = project_path.join("StdbModule.csproj");
let csproj = std::fs::read_to_string(&csproj_path)?;
std::fs::write(&csproj_path, csharp_csproj_for_target(&csproj, dotnet_major)?)?;
Ok(())
}
fn csproj_has_package_reference(content: &str, include: &str, version: &str) -> bool {
fn element_has_package_reference(element: &xmltree::Element, include: &str, version: &str) -> bool {
if element.name == "PackageReference"
&& element.attributes.get("Include").map(String::as_str) == Some(include)
&& element.attributes.get("Version").map(String::as_str) == Some(version)View on GitHub (pinned to fdd647dfac)