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
- Clear/regenerate the shader symbol cache so symbols are re-collected from the current owner types.
- Check the shader source for a renamed or removed member and update all references to match the owner type's current members.
- Verify inheritance chains: ensure the base shader that actually declares the member is the recorded OwnerType.
- 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
- Invalidate cached symbols whenever a defining shader is recompiled or edited.
- Always call TryResolveSymbol before the throwing import path.
- Keep symbol OwnerType pointing at the shader that actually declares the member.
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
- SortedList::internal error (
- Member not found
- Unsupported float width
- Unsupported constant type
- Cannot find type instruction for id
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)