stride3d/stride · error · Exception

Bad token

Error message

Bad token {tok}

What it means

The main token() loop of the Preprocessor encountered a token type it has no case for, so it throws a generic Exception("Bad token " + tok). This is a fall-through default in the tokenizer state machine and indicates a token kind the preprocessor cannot handle at top level.

Solutions

  1. Inspect the offending token text in the message and fix the source at that position
  2. Update/align the Lexer and Preprocessor versions so token enums match
  3. Check for binary/corrupted characters in the shader file (encoding issues)
  4. Catch Exception and log tok for diagnosis
Defensive patterns

Strategy: try-catch

Validate before calling

if (tok.Type == TokenType.INVALID) error(tok.Line, tok.Column, tok.Value as string);

Type guard

bool isHandled(TokenType t) => t is not TokenType.INVALID && Enum.IsDefined(t);

Try / catch

try { foreach (var tok in pp) Process(tok); } catch (Exception e) when (e.Message.StartsWith("Bad token")) { log.Error($"Unhandled token in source: {e.Message}"); }

Prevention

When it happens

Trigger: A Lexer produces a token type outside the set handled in the switch (e.g. Token.INVALID when CSYNTAX feature handling paths diverge, or a custom lexer emitting unexpected token kinds) — reached via the public Preprocessor token stream API.

Common situations: Custom/patched lexers feeding the preprocessor, corrupted or non-standard shader source producing odd tokens, version drift between lexer and preprocessor token enums.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Parsers/CppNet/Preprocessor.cs:1943

						return tok;
					if (source.isExpanding(m))
						return tok;
					if (macro(m, tok))
						break;
					return tok;

				case Token.P_LINE:
					if (getFeature(Feature.LINEMARKERS))
						return tok;
					break;

				case Token.INVALID:
					if (getFeature(Feature.CSYNTAX))
						error(tok, (String)tok.getValue());
					return tok;

				default:
                    throw new Exception("Bad token " + tok);
					// break;

				case Token.HASH:
					tok = source_token_nonwhite();
					// (new Exception("here")).printStackTrace();
					switch (tok.getType()) {
						case Token.NL:
							goto BREAK_LEX;	/* Some code has #\n */
						case Token.IDENTIFIER:
							break;
						default:
							error(tok,
								"Preprocessor directive not a word " +
								tok.getText());
							return source_skipline(false);
					}
					int	_ppcmd = ppcmds[tok.getText()];
					if (_ppcmd == null) {

View on GitHub (pinned to 96fad776d2)