Tencent/matrix · error
unterminated %%ifdef starting on line
Error message
unterminated %%ifdef starting on line %d
What it means
Lemon's input preprocessor tracks %ifdef/%ifndef/%else/%endif conditionals while reading the grammar file. If the end of the file is reached while a conditional block is still open (exclude != 0), it prints 'unterminated %ifdef starting on line %d' naming the line where the block began, and exits 1.
Solutions
- Add the missing %endif at the end of the conditional block reported by the start line
- Search the .y file for all %ifdef/%ifndef and verify each has exactly one matching %endif (nesting order matters)
- Check for misspelled conditional keywords near the reported start line
- If the block came from a merge, re-diff against the original file to recover the dropped %endif
Example fix
// before (foo.y) %ifdef FOO rule ::= A. // after %ifdef FOO rule ::= A. %endif
Defensive patterns
Strategy: validation
Validate before calling
# python pre-check balancing conditional directives in order
import re,sys
stack=[]
for n,line in enumerate(open(sys.argv[1]),1):
s=line.strip()
if s.startswith(('%ifdef','%ifndef')): stack.append(n)
elif s.startswith('%endif'): stack and stack.pop()
elif s.startswith('%else') and not stack: sys.exit(f'stray %else at line {n}')
if stack: sys.exit(f'unterminated %ifdef starting on line {stack[0]}') Prevention
- Run a conditional-balance linter over .y files in pre-commit/CI
- Avoid manual deletion of %endif lines during merges; re-diff conditional blocks
- Use consistent, exact keywords (%ifdef/%ifndef/%else/%endif)
- Keep conditional blocks small and locally scoped
When it happens
Trigger: A .y grammar file contains %ifdef or %ifndef without a matching %endif before EOF; a misspelled conditional keyword (e.g. `%endifs` or `%ednif`) that the scanner ignores; a nested conditional where one %endif was removed by an outer block's processing.
Common situations: Manual edits to grammar files that delete or comment out a %endif; merge conflicts resolved by dropping lines including %endif; copy-pasted conditional blocks where only part of the pair was copied; refactoring that moved rules across files leaving the opener behind.
Related errors
- Empty grammar.
- parsing conflicts.
- Unable to allocate memory for a new follow-set propagation…
- Can't allocate space for a filename.
- Can't open file " ".
AI-assisted analysis of Tencent/matrix@3b8293bd65 (2026-09-08).
Data as JSON: /api/errors/a5fcd3e871638c92.
Report an issue: GitHub.
Appendix: source
Thrown at matrix/matrix-android/matrix-sqlite-lint/src/lemon/lemon-gen/lemon.c:2423
for(n=0; z[j+n] && !isspace(z[j+n]); n++){}
exclude = 1;
for(k=0; k<nDefine; k++){
if( strncmp(azDefine[k],&z[j],n)==0 && strlen(azDefine[k])==n ){
exclude = 0;
break;
}
}
if( z[i+3]=='n' ) exclude = !exclude;
if( exclude ){
start = i;
start_lineno = lineno;
}
}
for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' ';
}
}
if( exclude ){
fprintf(stderr,"unterminated %%ifdef starting on line %d\n", start_lineno);
exit(1);
}
}
/* In spite of its name, this function is really a scanner. It read
** in the entire input file (all at once) then tokenizes it. Each
** token is passed to the function "parseonetoken" which builds all
** the appropriate data structures in the global state vector "gp".
*/
void Parse(gp)
struct lemon *gp;
{
struct pstate ps;
FILE *fp;
char *filebuf;
int filesize;
int lineno;
int c;View on GitHub (pinned to 3b8293bd65)