Tooling & environment
Windows / PowerShell / dotnet traps that corrupt source.
On engine 26.07 both [GameResource] and NavMesh.GetSimplePath are marked [Obsolete] (CS0618), so a zero-warnings build gate fails on them. Replace [GameResource(...)] with [AssetType(...)] and GetSimplePath with NavMesh.CalculatePath, which returns a NavMeshPath of NavMeshPathPoint (not List<Vector3>).
A project resource type that claims a file extension the engine already owns can lose a registration race, with no error. The losing type's ResourceLibrary.GetAll returns empty and files deserialize as the engine type instead. Which side wins is decided per editor launch. Audit the extension with asset_types before you commit to it.
s&box regenerates .csproj from the editor and gitignores them, so a fresh git worktree's Code/ and Editor/ folders have no project file and dotnet build fails MSB1009. Copy the csproj in, or, at a different depth, author one with absolute paths.
The editor can report a clean compile for both the game and editor compilers while the running assembly is still stale. A green status is necessary but not sufficient. Confirm the load with a symbol that is new this session.
Compiling an s&box game assembly outside the editor needs the exact csproj shape the editor generates, and even a perfectly green offline build cannot surface whitelist violations. The SB1000 analyzer runs only in the editor compile pass, so code can build with 0 errors and 0 warnings offline and still be rejected in-editor. Build the editor-generated Code/<project>.csproj directly and confirm against the editor compile_status, never the offline build alone.
Code under Code/ hotloads fine, but an Assets/ folder created AFTER the editor started never mounts: asset search finds nothing in it and asset_info reports no asset. It is not a dead watcher; the only fix is restarting the editor.
A Standalone export changes the data path, log filename, quit behaviour, boot flow, and convar timing versus the editor/published client. Tooling and automation built on editor assumptions silently miss files or spin, verified live on engine 26.07.22.
An s&box game csproj project-references the engine's Base Library csproj inside the Steam install. A first build or a rebuild writes generated intermediates into the engine tree even with an absolute OutputPath, and duplicate attribute files under the base addon then stop the engine booting. BaseIntermediateOutputPath is not the fix, it is a second trap. Clear the base addon's obj and .build folders to recover.
Angles uses .pitch/.yaw/.roll (lowercase) and Vector3 uses .x/.y/.z. Capitalized sightings in a codebase belong to unrelated component properties.
Calling .Result or .Wait() on the main thread against a Task from GameTask.RunInThreadAsync deadlocks forever, silently. The process stays alive and the window still responds, but the frame loop is dead. Only join these tasks with await, or compute synchronously on the main thread.
A fresh git worktree of an s&box project cannot dotnet build, because the editor generates Code/<project>.csproj and gitignores it, and the csproj references the Steam engine DLLs by relative paths tied to the main tree's directory depth. A naive copy fails with MSB3245 when the worktree nests one level deeper. The durable fix rewrites the csproj with absolute engine paths and redirects OutputPath into an isolated folder. That second half matters everywhere: the default OutputPath is the shared .vs/output/ folder with no project segment, so any CLI build on the machine writes into the same directory. A sibling build there empties a running editor's TypeLibrary, and every game component reads as MissingComponent while compile_status still reports Success. Build headless with the editor closed and output redirected, or pass -p:OutputPath to keep the build out of the shared directory.
Deriving a visual's facing from horizontal velocity causes 180-degree snaps on any momentum reversal. Lock facing to an attach-time azimuth for pendulums and oscillators.
Adding a public method to the game assembly and calling it from the editor-tools assembly in the same hot-reload pass throws MissingMethodException at runtime: both compile_status and dotnet build are green.
A custom GameResource with a file extension longer than 8 characters silently never registers as a compilable source type. Every asset fails with "no source file." Keep extensions to 8 lowercase chars or fewer.
Headless dotnet build is green while the in-editor compiler emits SB1000: Environment/IO/Process/reflection are banned in game code.
Razor HUD emoji and dashes die under Get-Content/Set-Content: edit with byte-safe UTF-8 APIs or a real editor.
The editor compiles and verifies its ProjectRoot working tree. A branch that lives only in a git worktree is invisible to it, and compile_status results silently reflect the wrong code.
compile_status is fully green and the editor accepts edits, but Play executes the OLD code: touch, syntax-error cycling, and play restart all fail. Only a full editor process restart clears it.
The engine ships its built-in [McpTool]s as full C# source, not compiled DLLs: check addons/tools/Code/Mcp/*.cs for canonical patterns before inventing your own.
Failed package compile leaves the editor running the last-good hotload: multi-symptom 'regressions' are often stale code.
A front-flip rotation uses _baseRot.Forward (not .Right) when FacingYawOffset is ±90°: the offset swaps which local axis is perpendicular to travel.
An unqualified FileSystem compiles in a game assembly but CS0104s in an editor assembly: fully-qualify Sandbox.FileSystem in editor code.
ERROR models or white materials persist after fixing the source: delete the compiled artifact AND touch the source file to force recompilation, or poke asset_compile per source file.
A git worktree at a different directory depth than the main checkout breaks the generated csproj's relative references to the sbox install: dotnet build fails with missing-assembly errors.
compile_status shows Success and dotnet build is green, but play mode reports errors for symbols and lines that no longer exist in source: the play-mode hotloader compiled a stale mid-edit snapshot.
The editor discovers a library under Libraries/ only if the folder contains exactly one .sbproj file. A hand-vendored library without one is silently ignored, producing a wall of CS0246 errors on every type it defines.
dotnet build reports 0 errors on .razor files the in-editor compiler rejects: the headless build doesn't surface the Razor errors the live editor's Roslyn compiler flags.
A headless dotnet build against the engine assemblies does not enforce the s&box sandbox access-control whitelist: code that builds clean headlessly can fail the editor compile with SB1000.
A library extraction seam covers only the headline behavior: every other side effect of the replaced code path silently disappears unless explicitly reproduced on the consumer side.
A library host project fails to compile a library-mounted .scene asset: the resource compiler probes a mangled path, and the scene silently becomes an empty impostor.
Model.Load of a missing vmdl can return the orange ERROR mesh with the requested path as its Name: check IsError, not just null. And a failed load is cached for the life of the editor PROCESS: play_stop/play_start won't clear it, only a fresh editor will.
Moving legacy assets out of a publish payload with git mv alone leaves compiled artifacts behind (they are gitignored), and a material/model-only dependency closure misses shared textures that kept assets still reference.
A consumer game plus a vendored library can be compile-gated fully offline using two scratch csprojs against the editor install's prebuilt base library DLL.
App 1892930 via SteamCMD runs a headless server with +game pointing at a local .sbproj: clients stream code/assets, no sbox.game publish required.
Re-setting a [ConVar] to the value it already holds is a silent no-op: the C# setter never runs, so a convar-triggered action does nothing, with zero console output. Statics survive Play stop/start, so a prior session leaves the value already set.
If sbox-launcher.exe stays open during a Steam update, files vanish mid-install. Validate via steam://validate/590830.
A C# static list/registry survives editor Play stop/start and code hotloads, holding references to destroyed GameObjects: gate iteration on IsValid(), don't rely on clearing alone. It can also mask a new scene's state when stale high-priority entries outrank it. Hand registrations back in OnDestroy.
s&box carries old static state forward on hotload and never re-runs static constructors: a registry entry added in source is absent at runtime despite green compile.
A structural .razor change can throw a hotload exception that deregisters the project's entire toolset while compile_status still reports Success. Restart the editor to recover.
The editor MCP port is one engine-global preference, not a per-project setting. When the configured port is already bound by another open editor, the second editor logs a bind failure and starts no MCP server at all; it does not auto-increment to a free port. Bump the port by hand before (or after) launching the second editor, and have agents discover the live port by scanning and matching the Project field instead of pinning a number.
The official s&box docs serve raw markdown by appending .md to any doc URL, and expose a full index at sbox.game/llms.txt. The site itself is a client-rendered Blazor app whose HTML contains no content, so scraping gets nothing.
A repeating red "Texture manager doesn't know about texture ... default_mask ... returning error texture" pair on engine/RenderSystem is base-menu-addon noise mounted into every project, not your content. It repeats per draw call. There is no supported way to mute it from game code. Filter it visually.
Sandbox.PlayerController's WalkSpeed / RunSpeed / DuckedSpeed / Speed are private serialized [Property] fields, so an external component can't cleanly scale player move speed (e.g. for a slow/root effect). WishVelocity is public but recomputed every fixed-update, so writing it is order-dependent. Swap in or subclass a controller that exposes a public knob.
The game-reachable engine surface has no scene/global time-scale multiplier: Scene.TimeScale does not exist, and the only TimeScale anywhere is on ParticleEffect. Sandbox.Time is read-only. A slow-mo / fast-forward feature must scale each system's own Time.Delta reads, or expose a hook for a future native mechanism.
A long-running process started over a Windows OpenSSH session is killed the moment the session closes -- use a Scheduled Task instead.
Get-Content/Set-Content re-encodes BOM-less UTF-8 as ANSI; CRLF files break \n-only search-replace: use byte-safe APIs.