clockworklabs/SpacetimeDB · error · anyhow::Error

Unsupported .NET SDK version: {major}. SpacetimeDB requires

Error message

Unsupported .NET SDK version: {major}. SpacetimeDB requires .NET SDK 8.0 or 10.0.

What it means

When generating a `global.json` for a C# module build, `dotnet_global_json(major)` only accepts .NET SDK majors 8 (pinning `8.0.100`, `rollForward: latestFeature`) and 10 (`10.0.100`, `rollForward: latestMinor`). Any other major — parsed from the project's csproj TargetFrameworks or SDK resolution — bails with this error listing the supported versions.

Source

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

use anyhow::Context;
use itertools::Itertools;
use std::collections::HashSet;
use std::ffi::OsString;
use std::fs;
use std::path::{Path, PathBuf};

pub(crate) fn parse_major_version(version: &str) -> Option<u8> {
    version.split('.').next()?.parse::<u8>().ok()
}

fn dotnet_global_json(major: u8) -> anyhow::Result<String> {
    match major {
        8 => Ok(r#"{"sdk":{"version":"8.0.100","rollForward":"latestFeature"}}"#.to_string()),
        10 => Ok(r#"{"sdk":{"version":"10.0.100","rollForward":"latestMinor"}}"#.to_string()),
        _ => anyhow::bail!("Unsupported .NET SDK version: {major}. SpacetimeDB requires .NET SDK 8.0 or 10.0."),
    }
}

#[derive(Debug)]
struct CsprojTargetFrameworks {
    path: PathBuf,
    majors: Vec<u8>,
}

impl CsprojTargetFrameworks {
    fn single_major(&self) -> Option<u8> {
        (self.majors.len() == 1).then_some(self.majors[0])
    }
}

/// Read the target framework major versions directly from the project's `.csproj` file.
/// Returns `net8.0`, `net10.0`, etc. from both `<TargetFramework>` and `<TargetFrameworks>`.
/// Multi-target projects do not imply a single selected SDK version; callers should use a

View on GitHub (pinned to 524b4487d9)

Solutions

  1. Change the module's TargetFramework to `net8.0` (or `net10.0`) and rebuild
  2. Install the matching .NET SDK (8.0 or 10.0) so the pinned version in the generated global.json can resolve
  3. Remove conflicting SDK pins from any checked-in global.json so the CLI-generated one applies
  4. If multiple frameworks are targeted, ensure the single-major case resolves to 8 or 10 (the code only auto-selects when exactly one major is present)

Example fix

<!-- before -->
<TargetFramework>net9.0</TargetFramework>
<!-- after -->
<TargetFramework>net8.0</TargetFramework>
Defensive patterns

Strategy: validation

Validate before calling

# Check the module's target framework before building
grep -qE '<TargetFramework>net(8|10)\.0</TargetFramework>' proj/*.csproj || echo 'unsupported TFN: use net8.0 or net10.0'

Type guard

// Parse supported majors before invoking the build (Rust-ish pseudocode)
fn supported_major(tf: &str) -> bool { matches!(tf, "net8.0" | "net10.0") }

Prevention

When it happens

Trigger: A C# module whose `.csproj` targets `net6.0`, `net7.0`, or `net9.0` (anything outside net8.0/net10.0), or an SDK-pinning setting that resolves to a different major, when running `spacetime build`/`publish` on it.

Common situations: Porting an existing C# project that targeted an older framework; machines with only .NET 9 installed (between the supported majors); templates or tutorials using unsupported TargetFramework values; SDK pinning via a hand-written global.json conflicting with the CLI's supported set.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16). Data as JSON: /api/errors/d397195a20e4ff68. Report an issue: GitHub.