stride3d/stride · error · InvalidOperationException

Symbol could not be imported because it was not found in…

Error message

Symbol {symbol} could not be imported because it was not found in its owner type {symbol.OwnerType}

What it means

Thrown as an InvalidOperationException during symbol import resolution: the parser tried to resolve a shader symbol (method or variable, including constant-buffer members) against its declared owner type, but no member with a matching SymbolID and type exists in that owner. This signals a broken or stale symbol table entry — the symbol's recorded OwnerType no longer contains the symbol, so import cannot proceed.

Solutions

  1. Clear/regenerate the shader symbol cache so symbols are re-collected from the current owner types.
  2. Check the shader source for a renamed or removed member and update all references to match the owner type's current members.
  3. Verify inheritance chains: ensure the base shader that actually declares the member is the recorded OwnerType.
  4. If writing parser code, guard with TryResolveSymbol (the public wrapper) instead of calling the throwing internal import path directly.

Example fix

// before: importing a symbol whose owner no longer has the member
symbolTable.ImportSymbol(staleSymbol);
// after: resolve first, only import when found
if (!symbolTable.TryResolveSymbol(ref staleSymbol, importContext))
    throw new InvalidOperationException($"Member '{staleSymbol}' no longer exists on {staleSymbol.OwnerType}; recompile the defining shader");
Defensive patterns

Strategy: validation

Validate before calling

// Resolve before importing; avoid the throwing path
if (symbol.OwnerType.Methods.Any(m => m.Symbol.Id == symbol.Id && m.Symbol.Type == symbol.Type) ||
    symbol.OwnerType.Variables.Any(v => v.Symbol.Id == symbol.Id && v.Symbol.Type == symbol.Type))
{
    symbolTable.ImportSymbol(ref symbol);
}

Type guard

static bool IsResolvableInOwner(Symbol s) =>
    s.OwnerType != null &&
    (s.Type is FunctionType
        ? s.OwnerType.Methods.Any(m => m.Symbol.Id == s.Id && m.Symbol.Type == s.Type)
        : s.OwnerType.Variables.Any(v => v.Symbol.Id == s.Id && v.Symbol.Type == s.Type));

Try / catch

try
{
    symbolTable.ImportSymbol(ref symbol);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("could not be imported"))
{
    logger.Warn($"Stale symbol {symbol}: {ex.Message}. Recompiling owner shader.");
    RecompileOwner(symbol.OwnerType);
}

Prevention

When it happens

Trigger: Calling the symbol-import routine with a Symbol whose OwnerType.Methods/Variables (or constant-buffer Members) do not contain an entry matching symbol.Id and symbol.Type — e.g. after a shader was recompiled or its type layout changed while cached symbols still point at the old owner.

Common situations: Stale shader caches after editing a shader class (renaming/removing a member that other shaders still reference); importing a method/variable via inheritance bases where the base class was rebuilt; mismatched overload resolution where the recorded symbol ID no longer matches any method signature in the owner type.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Parsers/Core/SymbolTypes.cs:632

                            if (c.Symbol.IdRef == 0 && context != null)
                            {
                                // Emit symbol
                                var shaderId = context.GetOrImportShader(symbol.OwnerType);
                                context.ImportShaderVariable(shaderId, ref c.Symbol, c.Flags);
                            }

                            symbol.IdRef = c.Symbol.IdRef;
                            if (!isCurrentShader)
                                symbol = symbol with { MemberAccessWithImplicitThis = c.Symbol.Type };

                            return symbol;
                        }
                    }
                }
            }
        }

        throw new InvalidOperationException($"Symbol {symbol} could not be imported because it was not found in its owner type {symbol.OwnerType}");
    }

    /// <summary>
    /// Try to resolve a symbol in shader or inherited shader. If <see cref="importContext"/> is null, you can use this method without importing type or symbol in a context (useful for type evaluation).
    /// </summary>
    /// <param name="symbolTable"></param>
    /// <param name="importContext">If not null, the method or symbol will be imported in this context.</param>
    /// <param name="id"></param>
    /// <param name="symbol"></param>
    /// <returns></returns>
    internal bool TryResolveSymbol(int id, [MaybeNullWhen(false)] out Symbol symbol)
    {
        if (TryResolveSymbolNoRecursion(id, out symbol))
            return true;

        // Process inherited classes
        // note: since it contains all indirectly inherited method too, which is why it is splitted with TryResolveSymbolNoRecursion
        foreach (var inheritedShader in InheritedShaders)

View on GitHub (pinned to 96fad776d2)