{"record":{"id":"0d16a11555fbab51","repo":"Stirling-Tools/Stirling-PDF","slug":"expected-primary","errorCode":null,"errorMessage":"Expected primary","messagePattern":"Expected primary","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"frontend/editor/src/core/utils/bulkselection/parseSelection.ts","lineNumber":237,"sourceCode":"      return this.buildProgression(progression.k, progression.c);\n    }\n\n    // Number or Range\n    const num = this.tryReadNumber();\n    if (num !== null) {\n      this.skipWs();\n      if (this.peek(\"-\")) {\n        // Range\n        this.consume(1);\n        this.skipWs();\n        const end = this.readRequiredNumber();\n        return this.buildRange(num, end);\n      }\n      return this.buildSingleton(num);\n    }\n\n    // If nothing matched, error\n    throw new Error(\"Expected primary\");\n  }\n\n  private buildSingleton(n: number): Set<number> {\n    const set = new Set<number>();\n    if (n >= 1 && n <= this.max) set.add(n);\n    return set;\n  }\n\n  private buildRange(a: number, b: number): Set<number> {\n    const set = new Set<number>();\n    let start = a,\n      end = b;\n    if (!Number.isFinite(start) || !Number.isFinite(end)) return set;\n    if (start > end) [start, end] = [end, start];\n    start = Math.max(1, start);\n    end = Math.min(this.max, end);\n    for (let i = start; i <= end; i++) set.add(i);\n    return set;","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/Stirling-Tools/Stirling-PDF/blob/9ef20dcab80b85041912f045e17a6aea1d08f969/frontend/editor/src/core/utils/bulkselection/parseSelection.ts#L219-L255","documentation":"Thrown by parsePrimary when the current token is not any recognizable primary element: not '(', not a keyword (even/odd), not a progression (kn+c), and not a leading number. The parser has exhausted all primary alternatives, so it cannot proceed. As with other parser errors, only surfaces in strict mode; otherwise CSV fallback applies.","triggerScenarios":"Input like '& 5' (operator with no left operand at primary position), '1-5 & & 7' (double operator), '*5' (bare multiplication), or an expression starting with a symbol that is not '(' or '!'. Also a leading '&', '|', or '-' where a primary is expected after an operator.","commonSituations":"User typed a doubled operator, started the expression with an operator, or used a symbol not in the grammar at a position requiring a value. Pasted text containing special characters. Non-strict mode swallows this into the CSV fallback.","solutions":["Ensure each operator ('&', '|', ',', '-') is surrounded by valid primaries, not by another operator.","Start the expression with a number, keyword (even/odd), '(', or '!'.","Remove stray symbols; the grammar accepts only the documented operators.","Use the diagnostics warning (non-strict) to locate the malformed token before enabling strict rejection."],"exampleFix":"// before\nparseSelectionWithDiagnostics('1-5 & & 7', max, { strict: true })\n// after\nparseSelectionWithDiagnostics('1-5 & 7', max, { strict: true })","handlingStrategy":"validation","validationCode":"function hasNoDoubledOperators(input: string): boolean {\n  return !/[&|]\\s*[&|]/.test(input) && !/^[&|]/.test(input);\n}\n\nif (!hasNoDoubledOperators(input)) {\n  showUser('Remove doubled or leading operators.');\n}","typeGuard":"function startsWithValidPrimary(input: string): boolean {\n  const trimmed = input.trimStart();\n  return /^[\\d(!]|^(even|odd)\\b/i.test(trimmed);\n}","tryCatchPattern":"try {\n  const { pages } = parseSelectionWithDiagnostics(input, maxPages, { strict: true });\n} catch (e) {\n  if (e instanceof Error && e.message === 'Expected primary') {\n    showUser('Each part of the expression must be a number, range, keyword, or group.');\n  } else { throw e; }\n}","preventionTips":["Avoid doubling operators ('&&', '||'); use single '&' or '|'.","Start the expression with a number, '(', '!', or even/odd.","Use non-strict mode to get a fallback and warning rather than an exception.","Provide inline examples of valid syntax."],"tags":["bulk-selection","parser","validation","syntax"],"backgroundTag":null,"analyzedSha":"9ef20dcab80b85041912f045e17a6aea1d08f969","analyzedAt":"2026-08-13T22:11:39.827Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}