{"record":{"id":"44aa49f318640247","repo":"mozilla/pdf.js","slug":"invalid-token-if-endif-declaration","errorCode":null,"errorMessage":"Invalid token if ... endif declaration.","messagePattern":"Invalid token if \\.\\.\\. endif declaration\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/core/xfa/formcalc_parser.js","lineNumber":1146,"sourceCode":"        throw new Error(Errors.func);\n      }\n      tok = this.lexer.next();\n    }\n  }\n\n  parseSimpleExpr(tok = null) {\n    return new SimpleExprParser(this.lexer).parse(tok);\n  }\n\n  parseIf() {\n    // 'if' '(' SimpleExpression ')' then ExpressionList\n    // ('elseif' '(' SimpleExpression ')' then ExpressionList )*\n    // ('else' ExpressionList)?\n    // 'endif'.\n    let elseIfClause = [];\n    let tok = this.lexer.next();\n    if (tok.id !== TOKEN.leftParen) {\n      throw new Error(Errors.if);\n    }\n\n    const [tok1, condition] = this.parseSimpleExpr();\n\n    tok = tok1 || this.lexer.next();\n    if (tok.id !== TOKEN.rightParen) {\n      throw new Error(Errors.if);\n    }\n\n    tok = this.lexer.next();\n    if (tok.id !== TOKEN.then) {\n      throw new Error(Errors.if);\n    }\n\n    const [tok2, thenClause] = this.parseExprList();\n    tok = tok2 || this.lexer.next();\n\n    while (tok.id === TOKEN.elseif) {","sourceCodeStart":1128,"sourceCodeEnd":1164,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/core/xfa/formcalc_parser.js#L1128-L1164","documentation":"Thrown by Parser.parseIf() when, immediately after the 'if' keyword, the next token is not '(' (TOKEN.leftParen). FormCalc if syntax is 'if '(' SimpleExpression ')' then ExprList ... endif', so the condition must be parenthesized.","triggerScenarios":"A FormCalc 'if x then ... endif' or 'if {x} then ...' where the opening parenthesis after 'if' is missing. Reached while parsing an XFA form script containing an if-statement.","commonSituations":"Author used brace-free or brace-style conditions (FormCalc mandates parentheses); typo; generator omitting '('; corrupted script bytes after 'if'.","solutions":["Wrap the condition in parentheses: 'if (cond) then ... endif'.","Do not substitute braces or bare expressions for the parenthesized condition.","Re-emit the script from a FormCalc authoring tool.","Lint every 'if'/'elseif' to confirm '(' follows."],"exampleFix":"// before\nif x > 0 then 1 endif\n// after\nif (x > 0) then 1 endif","handlingStrategy":"validation","validationCode":"// Each 'if' / 'elseif' must be followed by '('.\nfunction ifsOpenParen(src) {\n  return !/\\b(if|elseif)\\b(?!\\s*\\()/.test(src);\n}","typeGuard":null,"tryCatchPattern":"try {\n  bindFormCalcScript(xfaNode, src);\n} catch (e) {\n  if (e instanceof Error && /if \\.\\.\\. endif declaration/.test(e.message)) {\n    console.warn(\"FormCalc if missing '(' after keyword; skipping\", e.message);\n    return;\n  }\n  throw e;\n}","preventionTips":["Parenthesize every if/elseif condition.","Do not use braces or bare expressions for conditions.","Lint 'if'/'elseif' to confirm '(' follows."],"tags":["xfa","formcalc","parser","syntax","if"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}