GitbookIO/gitbook · error · ExpressionError
Invalid nodes found when parsing
Error message
Invalid nodes found when parsing
What it means
Thrown by ExpressionRuntime.evaluate in @gitbook/expr when jexpr parses the expression successfully but reports invalid nodes. This means the syntax was consumed by the lenient parser yet contains constructs the evaluator cannot compile, so evaluation is aborted rather than producing a wrong value.
Source
Thrown at packages/expr/src/runtime.ts:48
this.#parserOptions = {
ecmaVersion: 'latest',
sourceType: 'script',
allowHashBang: false,
locations: true,
};
this.#autocompleter = new AutoComplete(this, logger);
this.#logger = logger;
}
/**
* Evaluates an expression based on the given inputs/context.
*/
public evaluate(expr: string, inputs: object): unknown {
try {
const parsed = this.parse(expr);
if (parsed.invalidNodes.length > 0) {
throw new ExpressionError('Invalid nodes found when parsing');
}
return evaluate.sync<Expression>(parsed.result, inputs, {
functions: true,
withMembers: true,
generate: escodegen.generate,
});
} catch (error) {
throw error instanceof Error
? new ExpressionError(error.message)
: new ExpressionError('Unexpected error');
}
}
/**
* Evaluates an expression safely by returning the error instead of throwing when invalid.
*/
public safeEvaluate(View on GitHub (pinned to db67585ee2)
Solutions
- Run runtime.parse(expr) or getVariables(expr) as a pre-flight to detect invalid nodes before evaluating user input
- Simplify the expression to basic operators, member access, and literals that the evaluator supports
- If input is user-provided, validate/sanitize expressions and show an editor error instead of evaluating
- Report the expression to the @gitbook/expr maintainers if it's plain JS that should work
Example fix
// before
const result = runtime.evaluate('user. + 1', inputs);
// after
const result = runtime.evaluate('user.count + 1', inputs); Defensive patterns
Strategy: try-catch
Validate before calling
const parsed = runtime.parse(expr);
if (parsed.invalidNodes.length > 0) {
return fallbackValue;
} Try / catch
try {
return runtime.evaluate(expr, inputs);
} catch (error) {
if (error instanceof ExpressionError) {
return fallbackValue; // or surface to the editor
}
throw error;
} Prevention
- Pre-flight parse user expressions and check invalidNodes
- Restrict the expression grammar exposed in your UI
- Show validation errors in the editor before submission
When it happens
Trigger: Calling evaluate() with expressions containing unsupported syntax (novel ES constructs, unusual operators, or malformed fragments that only the error-tolerant parser accepts); expressions with stray tokens like 'a + + b' or incomplete member chains.
Common situations: User-authored expressions (filters, computed values) fed from a CMS or visual editor; copy-pasted JS snippets with syntax the evaluator's AST whitelist rejects; upgrading @gitbook/expr or its parser deps enabling new parse paths that now surface invalid nodes.
Related errors
- Empty or invalid expression
- Expected schema of object to be provided: ${schema.type}
- Unsupported schema type: ${schema.type}
AI-assisted analysis of GitbookIO/gitbook@db67585ee2 (2026-08-28).
Data as JSON: /api/errors/87b6a79041e20429.
Report an issue: GitHub.