stride3d/stride · error · InvalidOperationException

Shader could not be found

Error message

Shader {name} could not be found

What it means

ShaderLoaderBase.LoadExternalBuffer resolves a shader by name through a lazy factory. After re-checking the cache, it calls ExternalFileExists(name); if the named shader file is not present anywhere the loader looks, it throws InvalidOperationException "Shader {name} could not be found". It is the loader's explicit 'shader not found' signal, distinct from 'found but failed to load/compile'.

Solutions

  1. Verify the shader name spelling matches the .sdsl file name exactly (case-sensitive on some platforms).
  2. Check the shader source directories/asset registry actually contain the .sdsl file and that ExternalFileExists would resolve it.
  3. Ensure the shader file is included in the project so it is copied to the output directory.
  4. Confirm the cache key/defines used are not aliasing a nonexistent combined shader name (name+macros).

Example fix

// before
var effect = new EffectCompiler().LoadExternalBuffer("MyShder", macros, ...); // typo
// after
var effect = new EffectCompiler().LoadExternalBuffer("MyShader", macros, ...); // matches MyShader.sdsl
Defensive patterns

Strategy: validation

Validate before calling

if (!File.Exists(Path.Combine(shaderDir, name + ".sdsl")))
    throw new FileNotFoundException($"Shader source missing: {name}.sdsl");

Try / catch

try { loader.LoadExternalBuffer(name, macros, out var buf, out var h, out var cached); }
catch (InvalidOperationException ex) when (ex.Message.Contains("could not be found")) {
    ReportMissingShader(name); // surface asset pipeline problem
}

Prevention

When it happens

Trigger: Requesting a shader whose .sdsl file does not exist in any registered shader source directory; a typo in the shader name; requesting a shader that was never added to the shader source folders or SDSLC registry.

Common situations: Misspelled shader name in effect code; shader asset not copied to output / not in the asset dependency chain; differing shader directories between the editor and the compiled game.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/6ee73a168d6126ba. Report an issue: GitHub.

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Compilers/ShaderLoaderBase.cs:67

            if (ValidateCachedHashes(buffer))
                return true;
            // A dependency changed — invalidate and recompile
            isFromCache = false;
        }

        // Coordinate parallel compilations: only one thread compiles a given (name, macros) pair.
        var macrosHash = ComputeMacrosHash(defines);
        var macrosArray = defines.ToArray();
        var key = (name, macrosHash);

        var lazy = compilingShaders.GetOrAdd(key, _ => new Lazy<(ShaderBuffers, ObjectId)>(() =>
        {
            // Double-check cache (another thread may have finished between our check and this factory)
            if (Cache.TryLoadFromCache(name, null, macrosArray, out var buf, out var h) && ValidateCachedHashes(buf))
                return (buf, h);

            if (!ExternalFileExists(name))
                throw new InvalidOperationException($"Shader {name} could not be found");

            if (!LoadExternalFileContent(name, out var filename, out var code, out h))
                throw new InvalidOperationException($"Shader {name} could not be loaded");

            if (!LoadFromCode(filename, code, h, macrosArray, out buf))
                throw new InvalidOperationException($"Shader {name} could not be compiled");

            return (buf, h);
        }, LazyThreadSafetyMode.ExecutionAndPublication));

        try
        {
            var result = lazy.Value;
            buffer = result.Buffer;
            hash = result.Hash;
            isFromCache = false;
            return true;
        }

View on GitHub (pinned to 96fad776d2)