ssssssss-team/spider-flow · error · TemplateException

{message}

Error message

{message}

What it means

ExpressionError.error builds a caret-highlighted message pointing at the failing span within the expression line and throws freemarker.template.TemplateException with that message and location. The '{message}' placeholder in the error record simply stands for the generated, location-annotated message text.

Solutions

  1. Read the caret position in the message to find the exact character range that failed, then correct the expression syntax there.
  2. Verify all variables referenced in the expression exist in the execution context at that node.
  3. Test the expression in isolation (evaluate just the expression against sample context) before re-running the flow.

Example fix

// before (expression)
${a.b.c}  // a is null
// after
${(a.b.c)!'default'}
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate expression before execution: try compiling it against a sample context
try { expressionService.compile(expr); } catch (Exception e) { /* surface syntax error to user before run */ }

Try / catch

try {
  Object v = expressionEngine.execute(expr, context);
} catch (TemplateException e) {
  // message contains caret-marked location of the failing span in the expression line
  log.error("Expression failed: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Any failed expression evaluation routed through ExpressionError.error: invalid FreeMarker/Aviator expression syntax in a spider flow field, unknown variables in the expression, or a wrapped cause exception.

Common situations: Users type malformed expressions in the flow designer (unbalanced parentheses, wrong function name, referencing a variable that doesn't exist in context), or an expression worked in an older engine version but the syntax/variable changed.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of ssssssss-team/spider-flow@c799cca99c (2026-09-08). Data as JSON: /api/errors/cd26569f9aab8946. Report an issue: GitHub.

Appendix: source

Thrown at spider-flow-core/src/main/java/org/spiderflow/core/expression/ExpressionError.java:51

	/** Create an error message based on the provided message and location, highlighting the location in the line on which the
	 * error happened. Throws a {@link TemplateException} **/
	public static void error (String message, Span location, Throwable cause) {

		Line line = location.getLine();
		message = "Error (" + line.getLineNumber() + "): " + message + "\n\n";
		message += line.getText();
		message += "\n";

		int errorStart = location.getStart() - line.getStart();
		int errorEnd = errorStart + location.getText().length() - 1;
		for (int i = 0, n = line.getText().length(); i < n; i++) {
			boolean useTab = line.getText().charAt(i) == '\t';
			message += i >= errorStart && i <= errorEnd ? "^" : useTab ? "\t" : " ";
		}

		if (cause == null)
			throw new TemplateException(message, location);
		else
			throw new TemplateException(message, location, cause);
	}

	/** Create an error message based on the provided message and location, highlighting the location in the line on which the
	 * error happened. Throws a {@link TemplateException} **/
	public static void error (String message, Span location) {
		error(message, location, null);
	}

	/** Exception thrown by all basis-template code via {@link ExpressionError#error(String, Span)}. In case an error happens deep inside a
	 * list of included templates, the {@link #getMessage()} method will return a condensed error message. **/
	public static class TemplateException extends RuntimeException {
		private static final long serialVersionUID = 1L;
		private final Span location;
		private final String errorMessage;

		private TemplateException (String message, Span location) {

View on GitHub (pinned to c799cca99c)