ssssssss-team/spider-flow · error · RuntimeException

Reached the end of the source.

Error message

Reached the end of the source.

What it means

TokenStream.consume() advances past the current token and throws RuntimeException("Reached the end of the source.") when no token remains (hasMore() is false). Unlike next(), it is a plain RuntimeException used by parser routines (error, parseStatement, operator, parseUnaryOperator) that assume another token exists. It signals truncated or syntactically incomplete input.

Solutions

  1. Validate/complete the expression source before parsing (balanced operators, no trailing operators).
  2. Call hasMore() (or catch the RuntimeException) before/at consume() sites in custom parser extensions.
  3. Report a syntax error at the last token position to the user instead of surfacing the runtime exception.
  4. Fix the calling parser branch that consumes without checking end-of-input.

Example fix

// before
Token t = stream.consume();
// after
if (!stream.hasMore()) throw new ParseException("unexpected end of expression", stream.lastPosition());
Token t = stream.consume();
Defensive patterns

Strategy: try-catch

Validate before calling

// before running the parser, reject obviously truncated expressions
if (expr == null || expr.trim().isEmpty()) throw new IllegalArgumentException("empty expression");
if (expr.trim().matches(".*[+\-*/(<,]$")) throw new IllegalArgumentException("expression ends with a dangling operator: " + expr);

Try / catch

try {
    Token token = stream.consume();
} catch (RuntimeException e) {
    if ("Reached the end of the source.".equals(e.getMessage())) {
        throw new ParseException("Incomplete expression: expected another token", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling consume() after all tokens were consumed — e.g. parsing "a +" where parseUnaryOperator/operator expects an operand token that does not exist, or parseStatement running off the end of malformed input.

Common situations: Users feeding incomplete expressions to the spider-flow expression parser (missing closing tokens/operands); template fragments cut off by truncation; grammar paths that forget to check hasMore() before consuming.

Related errors


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

Appendix: source

Thrown at spider-flow-core/src/main/java/org/spiderflow/core/expression/parsing/TokenStream.java:39

		this.end = tokens.size();
	}

	/** Returns whether there are more tokens in the stream. **/
	public boolean hasMore () {
		return index < end;
	}
	
	public boolean hasNext(){
		return index + 1 < end;
	}
	
	public boolean hasPrev(){
		return index > 0;
	}

	/** Consumes the next token and returns it. **/
	public Token consume () {
		if (!hasMore()) throw new RuntimeException("Reached the end of the source.");
		return tokens.get(index++);
	}
	
	public Token next(){
		if (!hasMore()) throw new RuntimeException("Reached the end of the source.");
		return tokens.get(++index);
	}
	
	public Token prev(){
		if(index == 0){
			throw new RuntimeException("Reached the end of the source.");
		}
		return tokens.get(--index);
	}

	/** Checks if the next token has the give type and optionally consumes, or throws an error if the next token did not match the
	 * type. */
	public Token expect (TokenType type) {

View on GitHub (pinned to c799cca99c)