dianping/cat · error · Error
__halt_compiler() can only be used from the outermost scope
Error message
__halt_compiler() can only be used from the outermost scope
What it means
A semantic reduce action in the generated PHP parser (worker-php.js:5653-region table; the action yyn29 at line 3577-3580). The grammar accepts __halt_compiler() only via a special outermost-scope production; if it is reduced through the ordinary statement rule instead, the reduce action throws this plain Error. It mirrors PHP itself, where __halt_compiler() is only allowed at the top level of a file.
Source
Thrown at cat-home/src/main/webapp/assets/js/editor/worker-php.js:3579
PHP.Parser.prototype.yyn25 = function ( attributes ) {
this.yyval = [];
};
PHP.Parser.prototype.yyn26 = function ( attributes ) {
this.yyval = this.yyastk[ this.stackPos-(1-1) ];
};
PHP.Parser.prototype.yyn27 = function ( attributes ) {
this.yyval = this.yyastk[ this.stackPos-(1-1) ];
};
PHP.Parser.prototype.yyn28 = function ( attributes ) {
this.yyval = this.yyastk[ this.stackPos-(1-1) ];
};
PHP.Parser.prototype.yyn29 = function ( attributes ) {
throw new Error('__halt_compiler() can only be used from the outermost scope');
};
PHP.Parser.prototype.yyn30 = function ( attributes ) {
this.yyval = this.yyastk[ this.stackPos-(3-2) ];
};
PHP.Parser.prototype.yyn31 = function ( attributes ) {
this.yyval = this.Node_Stmt_If(this.yyastk[ this.stackPos-(7-3) ], {'stmts': Array.isArray(this.yyastk[ this.stackPos-(7-5) ]) ? this.yyastk[ this.stackPos-(7-5) ] : [this.yyastk[ this.stackPos-(7-5) ]], 'elseifs': this.yyastk[ this.stackPos-(7-6) ], 'Else': this.yyastk[ this.stackPos-(7-7) ]}, attributes);
};
PHP.Parser.prototype.yyn32 = function ( attributes ) {
this.yyval = this.Node_Stmt_If(this.yyastk[ this.stackPos-(10-3) ], {'stmts': this.yyastk[ this.stackPos-(10-6) ], 'elseifs': this.yyastk[ this.stackPos-(10-7) ], 'else': this.yyastk[ this.stackPos-(10-8) ]}, attributes);
};
PHP.Parser.prototype.yyn33 = function ( attributes ) {
this.yyval = this.Node_Stmt_While(this.yyastk[ this.stackPos-(5-3) ], this.yyastk[ this.stackPos-(5-5) ], attributes);
};
View on GitHub (pinned to e815e74d4c)
Solutions
- Move __halt_compiler(); to the outermost scope of the PHP file (no enclosing function/class/block).
- If you don't need it, delete the call — it exists only to let a script embed data after the PHP block.
- Remember everything after __halt_compiler(); is treated as literal data, so it must be the last executable statement.
Example fix
// before
<?php
function boot() {
__halt_compiler();
}
// after
<?php
function boot() {
// ...
}
__halt_compiler(); Defensive patterns
Strategy: validation
Validate before calling
// Static check before sending to the worker: __halt_compiler must be at depth 0.
function haltCompilerAtTopLevel(src) {
let depth = 0;
for (const line of src.split('\n')) {
for (const ch of line) {
if (ch === '{' || ch === '(') depth++;
if (ch === '}' || ch === ')') depth--;
}
if (/__halt_compiler\s*\(/.test(line) && depth !== 0) return false;
}
return true;
} Try / catch
try {
parser.parse(src);
} catch (ex) {
if (/__halt_compiler/.test(ex.message)) {
annotate({ line: parser.startAttributes && parser.startAttributes.startLine, message: ex.message });
} else throw ex;
} Prevention
- Keep __halt_compiler(); as the last statement at file scope, never inside functions/blocks.
- When refactoring installers, remember moving it into a function breaks both this parser and PHP itself.
- Treat everything after the call as embedded data — no PHP after it.
When it happens
Trigger: Writing __halt_compiler() anywhere but the outermost scope: inside a function, method, if/loop block, or closure — e.g. 'function f() { __halt_compiler(); }'. The parser reduces the inner-statement production, hits yyn29, and throws at line 3579.
Common situations: Template/PHAR tooling code where __halt_compiler is used to embed binary data, refactoring moves the call into a function, or copy-pasting installer stubs into class methods. Also hit while typing in the ACE PHP editor before the call is moved to file scope.
Related errors
- syntax error, unexpected + terminals[tokenId] + expectedStr
- attribute equal must after attrName
- attribute value must after "="
- attribute invalid close char('/')
- attribute value missed!!
AI-assisted analysis of dianping/cat@e815e74d4c (2026-08-14).
Data as JSON: /api/errors/04dc88b06381ea72.
Report an issue: GitHub.