stride3d/stride · error · Exception

: could not set entry point

Error message

{cross.CompilerSetEntryPoint(compiler, entryPoint.Value.RealName, entryPoint.Value.ExecutionModel)} : could not set entry point

What it means

Translate throws this when CompilerSetEntryPoint fails to select the requested entry point on the compiler. spirv-cross returns failure when the named entry point does not exist in the module or the ExecutionModel does not match the module's declared model for that name.

Solutions

  1. Call GetEntryPoints first and verify the desired RealName/ExecutionModel pair exists before passing it to Translate
  2. Re-fetch entry points whenever the shader module is recompiled instead of caching names
  3. Check name spelling/case exactly matches the SPIR-V OpEntryPoint name
  4. Confirm the ExecutionModel comes from the same module's entry-point list
  5. Pass null entryPoint to translate the default entry point and compare results

Example fix

// before
var hlsl = translator.Translate(Backend.Hlsl, ("mainPS", "main", ExecutionModel.Fragment));
// after
var eps = translator.GetEntryPoints(Backend.Hlsl);
var ep = eps.FirstOrDefault(e => e.RealName == "mainPS")
         ?? throw new InvalidOperationException($"Entry point 'mainPS' not found. Available: {string.Join(", ", eps.Select(e => e.RealName))}");
var hlsl = translator.Translate(Backend.Hlsl, (ep.RealName, "main", ep.ExecutionModel));
Defensive patterns

Strategy: validation

Validate before calling

var available = translator.GetEntryPoints(backend);
if (entryPoint != null && !available.Any(e => e.RealName == entryPoint.Value.RealName && e.ExecutionModel == entryPoint.Value.ExecutionModel))
    throw new InvalidOperationException($"Entry point '{entryPoint.Value.RealName}' ({entryPoint.Value.ExecutionModel}) not in module");

Try / catch

try { var src = translator.Translate(backend, entryPoint); } catch (Exception ex) when (ex.Message.Contains("could not set entry point")) { Log.Error($"Entry point '{entryPoint?.RealName}' invalid; available: {string.Join(", ", translator.GetEntryPoints(backend).Select(e => e.RealName))}"); throw; }

Prevention

When it happens

Trigger: Calling Translate(backend, entryPoint) with a RealName that is not an entry point in the SPIR-V (e.g. stale name after shader recompilation/renaming), or an ExecutionModel that disagrees with the module (e.g. passing Vertex for a fragment shader).

Common situations: Caching entry-point names from a previous shader version and reusing them after the effect was recompiled; mixing entry points across shader stages; case-sensitivity mistakes in the entry point name; getting names from a different SPIR-V module than the one being translated.

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/81aa6a7242e78d4b. Report an issue: GitHub.

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Compilers/SpirvTranslator.cs:110

            // RenderDoc's shader viewer when displaying the cross-compiled HLSL/GLSL.
            // OpLine in the SPIR-V is preserved for Vulkan/RenderDoc callstacks.
            cross.CompilerOptionsSetBool(compilerOptions, CompilerOption.EmitLineDirectives, 0);
            if (backend == Backend.Hlsl)
            {
                cross.CompilerOptionsSetUint(compilerOptions, CompilerOption.HlslShaderModel, 50);
                cross.CompilerOptionsSetBool(compilerOptions, CompilerOption.HlslPreserveStructuredBuffers, 1);
                // FXC rejects uninitialized loop-carried variables (from OpUndef phi inputs) with a
                // bogus "error X4555: cannot use casts on l-values" when they end up assigned in a
                // for-loop continue expression.
                cross.CompilerOptionsSetBool(compilerOptions, CompilerOption.ForceZeroInitializedVariables, 1);
            }
            cross.CompilerInstallCompilerOptions(compiler, compilerOptions);
        }

        if (entryPoint != null)
        {
            if (cross.CompilerSetEntryPoint(compiler, entryPoint.Value.RealName, entryPoint.Value.ExecutionModel) != Result.Success)
                throw new Exception($"{cross.CompilerSetEntryPoint(compiler, entryPoint.Value.RealName, entryPoint.Value.ExecutionModel)} : could not set entry point");
        }

        if (cross.CompilerCreateShaderResources(compiler, &resources) != Result.Success)
            throw new Exception($"{cross.CompilerCreateShaderResources(compiler, &resources)} : could not create shader resources");

        // HLSL: remove type_ prefix from cbuffer (they get names from struct instead of cbuffer variable itself)
        if (backend == Backend.Hlsl)
        {

            ReflectedResource* resourcesList;
            nuint resourcesCount;
            cross.ResourcesGetResourceListForType(resources, ResourceType.UniformBuffer, &resourcesList, &resourcesCount);
            for (uint i = 0; i < resourcesCount; ++i)
            {
                var resource = resourcesList[i];
                var cbufferName = Marshal.PtrToStringAnsi((IntPtr)resource.Name)!;
                if (cbufferName.StartsWith("type."))
                {

View on GitHub (pinned to 96fad776d2)