cakephp/cakephp · error · CakeException
Invalid format for MO translations file
Error message
Invalid format for MO translations file
What it means
After opening a .mo file, MoFileParser::parse() stats it and rejects it if fstat fails or the file is smaller than the 28-byte MO magic header (MO_HEADER_SIZE). This means the file exists but is too small/empty to be a valid GNU MO file. CakePHP throws the same message later when the magic number is wrong, so the file may be truncated or not a MO file at all.
Solutions
- Regenerate the .mo file with msgfmt (or cake i18n extract/compile pipeline) and verify size > 0
- Confirm the file is actually a compiled .mo (file magic via `file translation.mo`) and not a .po or HTML error page
- Re-upload/redeploy the translation file; verify integrity with checksum after transfer
- Add a pre-check: filesize($path) >= 28 before parsing
Example fix
// before
$entries = $parser->parse($path); // truncated .mo
// after
if (filesize($path) < 28) { // MoFileParser::MO_HEADER_SIZE
throw new RuntimeException("Truncated MO file: $path");
}
$entries = $parser->parse($path); Defensive patterns
Strategy: validation
Validate before calling
$size = @filesize($path);
if ($size === false || $size < 28) throw new RuntimeException("Truncated/invalid MO: $path"); Try / catch
try {
$entries = (new MoFileParser())->parse($path);
} catch (\Cake\Core\Exception\CakeException $e) {
if ($e->getMessage() === 'Invalid format for MO translations file') {
$entries = [];
} else { throw $e; }
} Prevention
- Verify .mo file sizes/checksums after build and deploy
- Regenerate .mo files with msgfmt instead of copying possibly truncated artifacts
- Avoid interrupting msgfmt/copy operations; write to temp then rename
- Add a smoke test that parses every shipped .mo file
When it happens
Trigger: Calling parse() on an empty file, a partially written/truncated .mo, a file whose stat fails, or on a non-MO file smaller than MO_HEADER_SIZE.
Common situations: msgfmt run interrupted leaving a 0-byte .mo; git LFS/checkout artifacts; copying a .po where a .mo was expected; disk full during deployment truncating the file.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- Cannot open resource
- Length must be > 0
- Could not find class
- Cannot open resource
- Cannot read file content of
AI-assisted analysis of cakephp/cakephp@1128eba9b0 (2026-09-12).
Data as JSON: /api/errors/aabc1f2bb2551e57.
Report an issue: GitHub.
Appendix: source
Thrown at src/I18n/Parser/MoFileParser.php:70
/**
* Parses machine object (MO) format, independent of the machine's endian it
* was created on. Both 32bit and 64bit systems are supported.
*
* @param string $file The file to be parsed.
* @return array List of messages extracted from the file
* @throws \Cake\Core\Exception\CakeException If stream content has an invalid format.
*/
public function parse(string $file): array
{
$stream = fopen($file, 'rb');
if ($stream === false) {
throw new CakeException(sprintf('Cannot open resource `%s`', $file));
}
$stat = fstat($stream);
if ($stat === false || $stat['size'] < self::MO_HEADER_SIZE) {
throw new CakeException('Invalid format for MO translations file');
}
/** @var array $magic */
$magic = unpack('V1', (string)fread($stream, 4));
$magic = hexdec(substr(dechex(current($magic)), -8));
if ($magic === self::MO_LITTLE_ENDIAN_MAGIC) {
$isBigEndian = false;
} elseif ($magic === self::MO_BIG_ENDIAN_MAGIC) {
$isBigEndian = true;
} else {
throw new CakeException('Invalid format for MO translations file');
}
// offset formatRevision
fread($stream, 4);
$count = $this->_readLong($stream, $isBigEndian);
$offsetId = $this->_readLong($stream, $isBigEndian);View on GitHub (pinned to 1128eba9b0)