stride3d/stride · error · LexerException
Error at
Error message
Error at {line}:{column}: {msg} What it means
Preprocessor.error reports preprocessing errors (raised from error, warning, pop_state, include) at a given line/column. When a PreprocessorListener is installed, the error is delegated to listener.handleError; with no listener, it throws LexerException("Error at line:column: msg") instead. It is the central funnel for directive-level failures such as failed #include or bad directives.
Solutions
- Install a PreprocessorListener (implementing handleError/handleWarning) so diagnostics are collected instead of thrown at the first problem.
- Fix the reported source location: check the file at the given line:column — for includes, verify the path and the include search paths passed to the Preprocessor.
- Correct the malformed preprocessor directive (#define, #if, #pragma) flagged by the message.
- Wrap preprocessing in try-catch on LexerException and surface line/column information to the user.
Example fix
// before: no listener, first directive error throws
var pp = new Preprocessor();
pp.addIncludePath("shaders");
// after: listener collects errors, preprocessing completes
var pp = new Preprocessor();
pp.setListener(new CollectingListener(errors));
pp.addIncludePath("shaders"); Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check includes and directives before preprocessing
foreach (var inc in Regex.Matches(src, @"#\s*include\s*[\"<]([^\">]+)"))
if (!ResolveOnIncludePaths(inc.Groups[1].Value, includePaths, out _))
report($"Include not found: {inc.Groups[1].Value}"); Try / catch
var errors = new List<Diagnostic>();
try
{
preprocessor.setListener(new CollectingListener(errors));
while ((tok = preprocessor.token()) != null) { /* ... */ }
}
catch (LexerException ex)
{
errors.Add(Diagnostic.Parse(ex.Message)); // "Error at L:C: msg"
} Prevention
- Always install a PreprocessorListener so all diagnostics are collected instead of aborting at the first error.
- Verify #include paths exist on the configured include search paths before preprocessing.
- Sanity-check directive syntax (#define/#if/#pragma) in a pre-pass or linter.
When it happens
Trigger: Any preprocessing error with no listener installed: a failed #include (file not found), malformed directives, state errors in pop_state, or error()-reported conditions during pragma handling.
Common situations: #include of a shader file whose path is wrong or not in the include search paths; syntax errors in #if/#define expressions; parsing shader sources with a Preprocessor configured without a listener so every warning-level issue escalates to an exception.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Found duplicate %YAML directive.
- Found incompatible YAML document.
- Found duplicate %TAG directive.
- While scanning a directive, find uknown directive name.
- While scanning a directive, did not find expected comment…
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/b48e06630deed3b5.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Parsers/CppNet/Preprocessor.cs:278
*
* @see #addInput(Source)
*/
public void addInput(FileInfo file) {
addInput(new FileLexerSource(file));
}
/**
* Handles an error.
*
* If a PreprocessorListener is installed, it receives the
* error. Otherwise, an exception is thrown.
*/
protected void error(int line, int column, String msg) {
if (listener != null)
listener.handleError(source, line, column, msg);
else
throw new LexerException("Error at " + line + ":" + column + ": " + msg);
}
/**
* Handles an error.
*
* If a PreprocessorListener is installed, it receives the
* error. Otherwise, an exception is thrown.
*
* @see #error(int, int, String)
*/
protected void error(Token tok, String msg) {
error(tok.getLine(), tok.getColumn(), msg);
}
/**
* Handles a warning.
*
* If a PreprocessorListener is installed, it receives theView on GitHub (pinned to 96fad776d2)