mozilla/pdf.js · error · Error

Invalid token in do ... end declaration.

Error message

Invalid token in do ... end declaration.

What it means

Thrown by Parser.parseBlock() in the FormCalc parser when a 'do ... end' block body has been parsed but the terminator keyword 'end' (TOKEN.end) is missing. FormCalc requires every block opened with 'do' to close with 'end'; any other token at that position raises Errors.block.

Source

Thrown at src/core/xfa/formcalc_parser.js:1055

    tok = this.lexer.next();
    if (tok.id === TOKEN.assign) {
      const [tok1, expr] = this.parseSimpleExpr(null);
      return [tok1, new Assignment(savedTok.value, expr)];
    }

    const parser = new SimpleExprParser(this.lexer);
    parser.pushOperand(new AstIdentifier(savedTok.value));

    return parser.parse(tok);
  }

  parseBlock() {
    const [tok1, body] = this.parseExprList();

    const tok = tok1 || this.lexer.next();
    if (tok.id !== TOKEN.end) {
      throw new Error(Errors.block);
    }

    return [null, new BlockDecl(body)];
  }

  parseVarDecl() {
    // 'var' Identifier ('=' SimpleExpression)?
    let tok = this.lexer.next();
    if (tok.id !== TOKEN.identifier) {
      throw new Error(Errors.var);
    }

    const identifier = tok.value;

    tok = this.lexer.next();
    if (tok.id !== TOKEN.assign) {
      return [tok, new VarDecl(identifier, null)];
    }

View on GitHub (pinned to 5903d58d58)

Solutions

  1. Verify that every 'do' block in the script is closed by exactly 'end'.
  2. Check for terminator confusion: blocks use 'end', for-loops use 'endfor', while uses 'endwhile', funcs use 'endfunc', ifs use 'endif'.
  3. Re-author the block in a FormCalc-aware tool to get correct matching closers.
  4. If untrusted input, catch the parse failure and skip the malformed block script.

Example fix

// before
do
  Sum(*)
endfor
// after
do
  Sum(*)
end
Defensive patterns

Strategy: validation

Validate before calling

// Verify each 'do' block is terminated by 'end' (simple heuristic).
function blocksBalanced(src) {
  const dos = (src.match(/\bdo\b/g) || []).length;
  const ends = (src.match(/\bend\b/g) || []).length;
  return dos === ends;
}

Try / catch

try {
  bindFormCalcScript(xfaNode, src);
} catch (e) {
  if (e instanceof Error && /do \.\.\. end declaration/.test(e.message)) {
    console.warn("FormCalc block missing 'end'; skipping", e.message);
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: A FormCalc block where the body expression list is followed by a token that is not 'end' (e.g. 'endif', 'endfunc', EOF, or an identifier). Triggered while parsing an XFA form script containing a 'do' block.

Common situations: Mismatched block terminators (using 'endfor' where 'end' is expected); truncated script that ends after the body; generator emitting the wrong closer; hand-authored FormCalc confusing 'do...end' with 'for...endfor'.

Understand the failure class

Related errors


AI-assisted analysis of mozilla/pdf.js@5903d58d58 (2026-08-13). Data as JSON: /api/errors/e43f583aac2fc651. Report an issue: GitHub.