the symptom, in your words

"Git worktree at different depth breaks sbox csproj relative references"

✓ verified on 26.07.15a
lane Tooling & environmentposted updated

▸ SYMPTOM

A headless dotnet build run from inside a git worktree fails with missing-assembly errors that look like a corrupted or missing sbox install, but the main checkout builds fine.

▸ CAUSE

The engine's generated project .csproj references the sbox install's assemblies via deep relative paths (~7 levels of ..\). These paths only resolve correctly from the main repo checkout's own directory depth.

A git worktree placed at a different depth (e.g. two levels deeper than the main checkout) breaks every one of those relative references. The relative path traversal doesn't reach the sbox install from the new depth, so every assembly reference fails to resolve.

▸ FIX

Build from a worktree using a worktree-local throwaway .csproj (gitignored, never committed) that replaces the relative references with absolute paths to the sbox install:

snippet
<!-- worktree-verify.csproj (gitignored) -->
<Project Sdk="Microsoft.NET.Sdk.Razor">
  <!-- Copy from generated .csproj but replace relative ../ refs -->
  <Reference Include="Sandbox.Game">
    <HintPath>C:\Program Files\Steam\steamapps\common\sbox\managed\Sandbox.Game.dll</HintPath>
  </Reference>
  <!-- ... other refs with absolute paths ... -->
</Project>

Direct the output to a scratch directory so the main checkout's live-editor assemblies are never touched by a background verify build.

The throwaway-csproj build can do more than syntax-check: the built assembly can execute pure logic headlessly against the install's Sandbox.System.dll, which can catch real runtime crashes (e.g. an ArgumentException in date parsing) before the in-editor gate. It still validates neither SCSS nor the engine whitelist. The in-editor compile_status remains the authority there. Delete the temp .csproj and obj/ before finishing so it never collides with the editor's generated project.

▸ WHY IT WORKS

Absolute paths resolve regardless of where the .csproj sits in the filesystem. The worktree-local file is never committed (gitignored), so it doesn't affect the main checkout or other developers. The generated .csproj in the main checkout continues to use the relative paths that work at its depth.

Verified on engine 26.07.15a: seen in a real project.
s&box moves fast; an undated fix is a liability. Spot a stale detail?
changelog
  • Added: throwaway csproj can also execute pure logic headlessly for runtime validation
  • Published

Want to know when new guides or fixes drop? Join the community to help build this out. Report gotchas, flag outdated fixes, or just lurk.

Join the Discord