Diagnostic Codes

Every diagnostic ShadowDusk emits carries a code. This page is the complete registry: look up the code you saw in your build output to find out what triggered it.

Two things worth knowing before you read the table:

  • Codes from the underlying compilers are passed through verbatim and are not listed here. When DXC, d3dcompiler_47, or vkd3d-shader rejects your shader, you get that compiler's own words, unedited, along with the file, line, and column it reported. ShadowDusk never rewrites or summarizes a diagnostic it did not produce.
  • SD0400SD0499 are always warnings. They flag constructs that compile successfully but are known to fail or silently misbehave at runtime on narrower OpenGL stacks (WebGL, ANGLE, strict Mesa drivers), where the engine's own error is a generic draw-time exception. They never reject a shader.
  • A few codes outside that range are warnings too, marked as such in the table: SD0007 (a ShaderToy conversion adjustment), SD0008 (an #include that only resolves because the file system ignores case), SD0104 (an unrecognized vertex-input semantic defaulted to TextureCoordinate, exactly as mgfxc defaults and warns), and SD0214 (DirectX12 DXIL compiled unsigned on a non-Windows host). Like every warning, they never gate output.

To see everything wrong with a shader in one pass, including warnings and across several targets, call ValidateAsync instead of compiling. See the In-Memory Quickstart.

ShadowDusk diagnostic code registry

The central registry of every diagnostic code ShadowDusk itself emits. Every code maps to exactly one condition (one historical exception is flagged below). When adding a new error, pick an unused number from the matching range and add it here in the same change.

Codes from the underlying compilers (DXC, d3dcompiler_47, vkd3d-shader) are passed through verbatim (constraint 5: fail loudly, no reformatting) and are not listed here.

Ranges

Range Owner
FX0001FX0099 FX9 pre-parser (FxPreParser / FxLexer)
SD0000 CLI informational notes (severity Note, never a failure)
SD0001SD0009 Preprocessor (#include handling), input-format detection, source-provenance notes, and the ShaderToy/GLSL front end
SD0010SD0019 Pipeline-level effect validation
SD0020SD0029 MGFX writer range guards, container/target guards, and source-level target-binding guards (e.g. SD0028)
SD0100SD0199 Reflection / transpilation backends
SD0200SD0299 Platform / backend availability
SD0300SD0399 FNA (fx_2_0) target
SD0400SD0499 GL portability lint (GlslPortabilityAnalyzer) — always warnings, never errors
SD0500SD0599 MGCB content-processor plugin
SD0600SD0609 Slang input frontend (SlangFrontend and its passes)
SD0610SD0619 SkSL converter (SkslConverter / SkslGlslMapper)
SD1900SD1999 Browser/WASM host backends
X0000X0099 CLI and pipeline general errors (mgfxc-style)

FX — FX9 pre-parser

Code Meaning
FX0001 Unexpected token during FX9 parsing.
FX0002 Source ended before the current construct was closed.
FX0003 Malformed compile expression in a pass.
FX0004 Unrecognized shader profile string.
FX0005 Duplicate technique name.
FX0006 Duplicate pass name within a technique.
FX0007 Annotation block opened but never closed.
FX0008 Missing required ; after a statement.
FX0009 sampler_state block opened but never closed.
FX0010 Unrecognized render-state key (non-fatal).
FX0011 Unknown character in effect source (e.g. @, `).
FX0012 Legacy D3D9 sampling intrinsic (e.g. tex2Dlod) whose arguments cannot be rewritten 1:1 to a modern Texture2D method.
FX0013 An SM4+ resource or sampler type (e.g. SamplerComparisonState) appeared in a shader targeting FNA's D3D9 fx_2_0 profile, where no SM1–3 lowering exists. Raised before the source reaches vkd3d, which does not reject these cleanly (a SamplerComparisonState makes its SM1 lowering take the whole process down with an access violation).
FX0014 A pass assigns HullShader, DomainShader, GeometryShader, or ComputeShader. MonoGame's and KNI's Effect model exactly two shader stages, so no compiler can produce a loadable effect containing one — a consumer-runtime limit, not a ShadowDusk gap (mgfxc refuses the same inputs). Replaces the nonsense FX0008 "missing ;" these used to produce. See plan/DONE/PHASE-58-extended-shader-stages.md for the measured evidence and the conversion question.

SD — ShadowDusk pipeline

Code Meaning Emitted by
SD0000 Note. Informational output from the CLI, never a failure — currently the drivable effect parameters listed by --print-uniforms. PipelineRunner
SD0001 #include file not found on any search path. ShaderError.IncludeNotFound
SD0002 Circular #include (true cycle on the include stack; a diamond include is legal). ShaderError.CircularInclude
SD0003 Note. A ShaderToy/GLSL input was converted to .fx and that generated HLSL failed to compile — the diagnostics that follow refer to the generated source, not your original line numbers. PipelineRunner
SD0004 #include file was found on a search path but could not be read (locked, access denied, or deleted between the existence check and the read). FileSystemIncludeResolver
SD0005 Input format could not be detected: the source has no HLSL technique block and no ShaderToy mainImage / void main entry point. Pass --input-format fx or --input-format glsl. InputFormatDetector
SD0006 ShaderToy/GLSL front-end conversion failed: a construct outside the supported single-pass image subset (e.g. mainSound / mainVR / mainCubemap, or a malformed mainImage signature). Located on the original .glsl, not the generated .fx. PipelineRunner, ShaderFiddle.Web
SD0007 Warning. A non-fatal ShaderToy/GLSL conversion adjustment (e.g. a local auto-renamed because it shadows a called function, or a dropped standalone void main() wrapper). Located on the original .glsl. PipelineRunner, ShaderFiddle.Web
SD0008 Warning. An #include resolved only because this host's file system ignores case: the spelling in the directive differs from the file's real name by case alone (#include "shared/macros.fxh" for a file named Shared/Macros.fxh). Android, Linux, and case-sensitive APFS do not ignore case, so the same shader fails there with SD0001. Match the on-disk spelling. Only the segments the directive itself spells are checked — the absolute prefix above them is your machine's own layout and never ships. Preprocessor
SD0010 Effect source contains no techniques. CompilationPipeline
SD0011 Unrecognised value for a render-state key. RenderStateParser
SD0012 Internal: a GL uniform in the rewriter's register layout has no matching reflected effect parameter — the GLSL uniform layout and the reflection diverged. A ShadowDusk bug if ever seen. CompilationPipeline
SD0013 A pass compile <target> token does not resolve (after macro expansion) to a recognized shader profile — e.g. a typo (compile A …), an undefined *_SHADERMODEL macro (the #if OPENGL … #else … header was removed), or a profile-shaped-but-bogus literal (ps_9_9). Matches mgfxc/fxc's unrecognized compiler target. Fires on the GL/DX/Vulkan AND the FNA path. CompilationPipeline
SD0014 A pass compile <target> resolves to a profile whose stage prefix does not match the slot it is bound to — e.g. VertexShader = compile ps_3_0 … (a ps_* profile in a VertexShader slot) or PixelShader = compile vs_3_0 …. mgfxc/fxc reject this cross-stage binding. GL/DX/Vulkan path; the FNA path reports the same condition as SD0300 via ResolveFnaProfile. CompilationPipeline
SD0015 DirectX target only. A pass compile <target> resolves to a recognized profile that is nevertheless below MonoGame's DirectX_11 floor — e.g. compile ps_3_0 …, or the legacy #if OPENGL … #else … header that names SM3 in both arms. mgfxc rejects these with "Invalid profile 'vs_3_0'. Vertex shader 'VSMain' must be SM 4.0 level 9.1 or higher!"; ShadowDusk used to compile them, so the effect built here and then failed the consumer's real Content Pipeline build. Accepted set (measured against the pinned mgfxc): *_4_0_level_9_1, *_4_0_level_9_3, *_4_0, *_4_1, *_5_0 — note that *_4_0_level_9_0 and every SM6 profile are refused too. Distinct from SD0013 (token is not a profile at all) and SD0014 (profile's stage does not match its slot). CompilationPipeline
SD0020 Constant-buffer size exceeds the MGFX int16 maximum. MgfxWriter
SD0021 Shader index exceeds the MGFX int16 maximum. MgfxWriter
SD0022 A count/index serialized as a single byte in the .mgfx shader record is outside 0–255 (samplers, constant-buffer indices, vertex attributes, sampler parameter index). MgfxWriter
SD0023 CompilerOptions.MgfxVersion is outside the MGFX header's byte range (0–255). CompilationPipeline
SD0024 A sampler_state member has an unparseable value for a recognized key (MinFilter/MagFilter/MipFilter/Filter, AddressU/V/W, BorderColor, MaxAnisotropy, MaxMipLevel, MipLodBias). MgfxSamplerStateResolver
SD0025 The Vulkan target was requested together with the KNIFX container (KNI ships no Vulkan platform). CompilationPipeline
SD0026 A shader declares more than one constant buffer for a single stage on the Vulkan target, which the format does not support — merge the globals into one cbuffer. CompilationPipeline
SD0027 The DirectX12 target was requested together with the KNIFX container (KNI ships no DX12 platform). CompilationPipeline
SD0028 Vulkan target: two distinct textures are sampled through one shared sampler in the same live code path — both would land on one combined-image-sampler descriptor, leaving the second unbound at draw. Located at the offending Sample call; give each texture its own SamplerState. (SD0213 is this condition's post-compile reflection backstop.) VulkanTextureSamplerBindingRewriter
SD0100 SPIRV-Cross SPIR-V→GLSL transpilation failed (includes a SPIR-V blob whose byte length is not a multiple of 4). SpirvCrossGlslTranspiler
SD0101 Pure-managed reflection failed (DXBC RdefReader, SpirvReflector). RdefReader, SpirvReflector
SD0102 Native DXIL reflection (ID3D12ShaderReflection) failed. DxilReflectionExtractor
SD0103 SPIRV-Cross native library missing or unloadable (run tools/restore.ps1). SpirvCrossGlslTranspiler
SD0104 Warning. A vertex-input semantic is not one ShadowDusk recognizes, so its attribute defaulted to VertexElementUsage.TextureCoordinate with the trailing numeric index. The value is deliberately unchanged — real mgfxc defaults exactly the same way, and it also prints a warning when it defaults, so a drop-in replacement must warn rather than reject (bug-hunt 2026-07-27 N5). Matters because a typo (TEXCORD0 for TEXCOORD0) silently mints a phantom TextureCoordinate attribute that MonoGame's VertexInputLayout then demands from the vertex declaration; the only symptom is a failed draw with no reference back to the shader. Raised on the Vulkan (SPIR-V) and DirectX12 (DXIL) attribute-table paths, the two targets that write this table. VertexSemanticMapper via SpirvVertexInputReflector, DxilVertexInputReflector
SD0200 Metal target not yet supported. CompilationPipeline
SD0201 A capability-profile shader feature (e.g. vertex texture fetch, texture arrays) has no shipping runtime support yet and cannot be enabled. Reserved for a future runtime proven to consume it. ShaderFeatureSupport
SD0210 Two historical meanings (known shared code): (a) the d3dcompiler_47 oracle backend refused the request (requires Windows, or a ProfileOverride it never serves); (b) the MonoGame GLSL rewriter could not lower a construct to MonoGame's GL dialect — incl. int/bool/mat3/struct uniform-block members, a whole-array uniform use, or any surviving reference to a rewritten uniform block. D3DCompilerShaderCompiler, CompilationPipeline
SD0211 vkd3d-shader native library missing or unloadable (run tools/restore.ps1). Vkd3dShaderCompiler
SD0212 vkd3d-shader compile failed and emitted no diagnostic text at all (unparseable non-empty text passes through verbatim as X0000). Vkd3dCompileContract
SD0213 Vulkan target: reflection shows two distinct textures co-located onto a single combined-image-sampler binding — the second texture would silently sample the first's data on DesktopVK. The post-compile backstop of SD0028, for shared-sampler shapes the source-level scan cannot see. Give each texture its own SamplerState (or explicit register). CompilationPipeline
SD0214 Warning. DirectX12 DXIL compiled on a non-Windows host is unsigned (dxil.dll validation/signing is Windows-only): it loads only with Windows Developer Mode enabled, and retail D3D12 rejects it at pipeline-state creation. Compile DirectX12 effects on Windows. DxcShaderCompiler
SD0215 Retired (Phase 51 A7). Rejected sampler registers that were not contiguous from s0, because the GL record was named ps_s{sampler.BindSlot}. The record index is now the combined sampler's declaration position, so bind slots are never consulted for GL naming and register(s3) compiles correctly. Do not reuse this number.
SD0216 Retired (Phase 51 A7). Rejected the shared-SamplerState shape (N textures through one sampler) because the GL sampler table was keyed on the reflected samplers and could not name every ps_s{k} the GLSL declared. The table is now keyed on the (texture, sampler) pairs, so the shape compiles as mgfxc does. Do not reuse this number.
SD0217 OpenGL target: the combined-sampler declaration order the GL sampler table must mirror could not be determined from the SPIR-V — an input shape SpirvCombinedSamplerPairs does not model (an already-combined sampled image at module scope, an array/struct of separate samplers, a sampling operand that does not resolve to a module-level declaration), or an internal mismatch between the derived pair count and the number of sampler uniforms the emitted GLSL declares. Never raised by ordinary HLSL. SpirvCombinedSamplerPairs, CompilationPipeline
SD0300 FNA profile policy violation (SM4+/SM1 profile, or stage/profile prefix mismatch). CompilationPipeline.ResolveFnaProfile
SD0301 D3D9 CTAB reflection failed. CtabReader
SD0302 fx_2_0 effect validation failed at write time. Fx2EffectWriter
SD0303 FNA effect build failed. Fx2EffectBuilder
SD0304 Retired (Phase 39). Guarded "FNA unavailable on WASM" back when the browser host had no DXBC path. The vkd3d-shader WASM build removed the condition, so the guard no longer exists. Do not reuse this number.
SD0305 MojoShader-compatibility bytecode patch failed. D3d9BytecodePatcher
SD0400 Warning. A gradient op (dFdx/dFdy/fwidth) sits inside a loop with a divergent exit (conditional break/discard) in the emitted GL fragment source. ANGLE Direct3D11 (WebGL in every Windows browser) silently evaluates such derivatives to 0.0; fxc warns X3553 and force-unrolls the same HLSL (issue #141). GlslPortabilityAnalyzer
SD0401 Warning. A pass with no vertex shader whose pixel shader reads interpolants SpriteBatch's built-in SpriteEffect VS never writes (anything beyond COLOR0 → vFrontColor / TEXCOORD0 → vTexCoord0). Drawn with SpriteBatch on GL, the program link fails on strict drivers at the FIRST draw with the engine's generic exception. GlslPortabilityAnalyzer
SD0402 Warning. A loop shape outside GLSL ES 1.00 Appendix A in the emitted GL source (header-less for (;;), empty-increment for with the index advanced in the body, while, or a genuine do-while) — may fail to load on WebGL1 / KNI Reach (issue #138); desktop GL, WebGL2, and KNI HiDef are unaffected. GlslPortabilityAnalyzer
SD0403 Warning. A GLSL-1.30+/ES-3.00-only construct survived into the versionless emitted GL source (transpose, sinh-family, isnan/isinf, texelFetch, bit-cast builtins, switch, uint types/literals, non-square matrices, integer shifts, the integer bitwise/modulo operators & | ^ ~ %, or a round/roundEven/trunc a lowering missed). Lenient desktop drivers accept it; strict front ends (macOS OpenGL, Mesa, WebGL1) reject it at Effect-load time — the class behind issues #149 and #163. GlslPortabilityAnalyzer
SD0500 MGCB plugin: the ShaderProfile processor parameter names a profile ShadowDusk does not have (valid: DirectX_11, DirectX_12, OpenGL, Vulkan). Leave it empty to derive the target from the content project's /platform:. ShadowDuskEffectProcessor
SD0501 MGCB plugin: the content project's /platform: names a platform ShadowDusk has no backend for (the consoles). Fails the build rather than emitting a GL artifact that runtime cannot load. ShadowDuskEffectProcessor
SD0502 MGCB plugin: invalid DxbcBackend processor parameter (only vkd3d, d3dcompiler). The plugin-side twin of the CLI's X0006. ShadowDuskEffectProcessor
SD0600 Slang frontend: a Slang-only language feature (import, module, extension, associatedtype, generics — named in the message) appeared in the source. ShadowDusk compiles the HLSL-compatible subset of Slang: the shader body goes through the same pipeline as every .fx, with nothing extra to install on any platform (the deliberate trade, owner direction 2026-08-13 — no Slang toolchain is shipped or invoked, so features with no HLSL meaning have nothing to lower to). Rewrite the construct in plain HLSL terms. Subtler Slang-isms this courtesy scan misses fall through to DXC, whose own verbatim diagnostics apply. SlangFrontend
SD0602 Slang frontend: an entry point is [shader("...")] for a stage no supported consumer runtime can load (compute, mesh, the raytracing set, …). Stock MonoGame and KNI Effects hold exactly two stages — vertex and pixel (the Phase 58 measurement behind FX0014) — so this is a runtime limit, not a ShadowDusk gap, and it is rejected loudly by name rather than silently skipped. SlangEntryScanner
SD0603 Slang frontend: no [shader("vertex")] / [shader("fragment")] entry points found. Slang has no technique/pass concept, so the attributes are the only statement of intent ShadowDusk can synthesize the technique from. SlangEntryScanner
SD0604 Slang frontend: more than one entry point for the same stage. One .slang synthesizes one technique with at most one vertex and one pixel entry; split extra entries into separate files. SlangEntryScanner
SD0610 SkSL converter: the pass compiles a vertex shader (named in the message), or has no pixel shader. SkSL runtime effects have no vertex stage (a Skia platform limit); only pixel-only passes convert, and a vertex shader is refused rather than silently dropped. SkslConverter
SD0611 SkSL converter: the pixel shader reads an interpolant (named in the message) that an SkSL runtime effect cannot supply — runtime effects have no varyings at all; a pixel shader gets the coordinate plus uniforms. Refused by default (Gum's own hand-written SkSL port silently dropped its COLOR0 tint exactly this way); TreatVaryingsAsUniforms is the documented, warned-about opt-in that substitutes a per-draw uniform. SkslGlslMapper
SD0612 SkSL converter: a texture is sampled at computed coordinates. SkSL's .eval() takes child-space pixel coordinates and a runtime effect cannot know a child's bounds, so converting computed-UV sampling could silently read the wrong texels — refused rather than guessed. Sampling at the interpolated TEXCOORD0 (the 1:1 post-process case) converts. SkslGlslMapper
SD0613 SkSL converter: a construct with no SkSL runtime-effect equivalent (named in the message): gl_* builtins, derivatives (dFdx/dFdy/fwidth), LOD/offset/fetch sampling, or a multi-render-target output. Refused rather than approximated. SkslGlslMapper
SD0614 Warning. SkSL converter: a uniform was synthesized that the consumer's draw code MUST set — ShadowDusk_Resolution (output size in pixels, when the shader uses its UV arithmetically) or a TreatVaryingsAsUniforms substitution. Every synthesized uniform is also listed in SkslConversion.SynthesizedUniforms. SkslGlslMapper
SD0615 SkSL converter: the effect has multiple techniques or passes. An SkSL runtime effect is a single fragment function, so converting one pass and dropping the rest would be a silent guess — split the effect instead. SkslConverter
SD1900 Browser/WASM DXC backend failed. JsDxcShaderCompiler
SD1901 Browser/WASM SPIRV-Cross backend failed. JsSpirvToGlslTranspiler
SD1902 Browser/WASM vkd3d backend failed. WasmVkd3dShaderCompiler
SD1903 Synchronous Compile() called before the WASM compiler was initialized. WasmCompilerInitialization

X — CLI / general (mgfxc-style)

Code Meaning
X0000 A diagnostic from the underlying compiler, passed through as-is: either a parsed file:line:col entry (DXC emits no per-diagnostic codes) or, when nothing parses, the compiler's complete text VERBATIM as the message (never a generic sentence). The …with no diagnostics message form means the compiler failed while emitting no text at all.
X0001 Source file could not be read (I/O or access denied).
X0002 Output file could not be written (I/O or access denied).
X0003 Missing required CLI argument (<SourceFile> / <OutputFile>).
X0004 Unknown CLI profile.
X0005 Invalid --mgfx-version value (only 10 and 11).
X0006 Invalid /DxbcBackend value (only vkd3d, d3dcompiler).
X0007 CLI compile timed out (5-minute watchdog).
X0008 Invalid --target-runtime value (only monogame-gl, monogame-dx, monogame-gl-v11, kni-knifx, fna).
X0009 A CLI flag that requires a value (/I, --mgfx-version, --target-runtime, …) reached the end of the argument list with no value supplied.
X0010 Platform not supported by ShadowDusk (e.g. PlayStation4, XboxOne, Switch).
X0011 Invalid --input-format value (only auto, fx, glsl).
X0099 Unexpected internal error (catch-all; a bug if a consumer ever sees it).