Severity: error
Category: parser
Stage: Stage 1
Description
The parser entered phrase-mode error recovery three times on the same top-level item (statement, declaration, or expression) without successfully parsing the item to completion. After three consecutive phrase-recovery failures the parser considers the item unrecoverable and abandons further recovery for it.
When SJS-P099 is emitted:
- The per-item phrase-recovery counter has reached 3.
- Phrase mode is disabled for the remainder of the current item.
- The parser escalates immediately to panic mode at the item boundary — it discards tokens
until it reaches a synchronisation token for the enclosing
<Statement>or<Program>production (seespecs/parser-recovery.md§Synchronisation Sets). - Parsing resumes at the next top-level item. Diagnostics from subsequent items are reported normally; only the single bad item is abandoned.
This threshold prevents the parser from emitting an unbounded cascade of phantom error messages for a single malformed item. In practice the three-failure limit means SJS always reports at least a few useful diagnostics per item before giving up.
See specs/parser-recovery.md §Phrase-Mode Recovery for the authoritative algorithm.
Example
// ✗ A heavily malformed statement triggers SJS-P099
function foo() {
const result = bar(1, (2 + ### * 4), 5)
// ^^^ — phrase recovery 1: SJS-P001 (unexpected '###')
// ^ — phrase recovery 2: SJS-P001 (unexpected '*'; expected ')')
// ^ — phrase recovery 3: SJS-P001 (unexpected ')'; expected ')')
// — SJS-P099: recovery abandoned; skipping to next statement
}The diagnostics emitted for the example above (in order):
SJS-P001 error 2:17 Unexpected token '###'; expected expression
SJS-P001 error 2:18 Unexpected token '*'; expected ')'
SJS-P001 error 2:22 Unexpected token ')'; expected ')'
SJS-P099 error 2:3 Too many parse errors; recovery abandoned for this item
After SJS-P099 the parser resumes at } (the sync token for <Statement> / <FunctionDecl>
body) and continues parsing the rest of foo's body — or, if foo itself is abandoned, the
top-level program.
Fix
Correct the underlying syntax errors that triggered the three phrase-recovery attempts. Typically this means:
- Read the first SJS-P001 (or more specific code) reported for the item — it usually points directly at the root cause.
- Fix that error, then recompile. Subsequent phantom errors usually disappear once the first is resolved.
// ✓ correct — bad token removed; expression is now valid
function foo() {
const result = bar(1, (2 + 3) * 4, 5)
}Notes
- SJS-P099 is never emitted for a well-formed file; it only appears when there are already three preceding SJS-P00x diagnostics for the same item.
- The item boundary at which escalation occurs is always the smallest enclosing top-level
construct: a
<Statement>inside a function body, or a<Declaration>at the module level. The parser never abandons recovery above the<Program>level. - The per-item phrase-recovery counter is reset for each new top-level item, so a file with multiple badly-formed items may emit SJS-P099 more than once.
Related codes
SJS-P001— unexpected token (the diagnostic that increments the phrase-recovery counter)SJS-P002— unexpected end of fileSJS-P003— invalid syntax in type annotationSJS-P004— invalid sum type declarationSJS-P005— invalid match expression