symfony/translation · error · InvalidResourceException

MO stream content has an invalid format.

Error message

MO stream content has an invalid format.

What it means

MoFileLoader reads GNU gettext MO (machine object) files. Before parsing it checks the file is at least MO_HEADER_SIZE bytes; if not, the stream cannot contain a valid MO header and InvalidResourceException is thrown.

Solutions

  1. Compile the .po catalogues with `msgfmt messages.po -o messages.mo` and deploy the resulting .mo files.
  2. Check the .mo file size: it must be at least 28 bytes; `ls -l` or `wc -c` will reveal empty/truncated files.
  3. Re-run the translation build step and verify it exits 0 before packaging artifacts.
  4. If the file is genuinely corrupt, regenerate it from the .po source or VCS.

Example fix

// before
$loader->load('messages.po', 'en'); // raw PO, not compiled MO
// after
exec('msgfmt messages.po -o messages.mo');
$loader->load('messages.mo', 'en');
Defensive patterns

Strategy: validation

Validate before calling

clearstatcache(true, $file);
if (!is_file($file) || filesize($file) < 28) {
    throw new \RuntimeException(sprintf('%s is not a compiled MO file (too small)', $file));
}

Try / catch

try {
    $catalogue = $loader->load($moFile, $locale);
} catch (InvalidResourceException $e) {
    error_log('Invalid MO file: '.$e->getMessage());
    $catalogue = new MessageCatalogue($locale);
}

Prevention

When it happens

Trigger: loadResource() on an empty, truncated, or non-MO file smaller than the 28-byte MO header — e.g. passing a .po source file where a compiled .mo is expected, or a zero-byte artifact from a failed msgfmt run.

Common situations: Deploying .po files instead of compiled .mo files, msgfmt failing silently in CI so empty .mo files get committed, incomplete uploads.

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


AI-assisted analysis of symfony/translation@ae9e8a51bc (2026-09-15). Data as JSON: /api/errors/2989a21a47ea0194. Report an issue: GitHub.

Appendix: source

Thrown at Loader/MoFileLoader.php:49

    public const MO_BIG_ENDIAN_MAGIC = 0xDE120495;

    /**
     * The size of the header of an MO file in bytes.
     */
    public const MO_HEADER_SIZE = 28;

    /**
     * Parses machine object (MO) format, independent of the machine's endian it
     * was created on. Both 32bit and 64bit systems are supported.
     */
    protected function loadResource(string $resource): array
    {
        $stream = fopen($resource, 'r');

        $stat = fstat($stream);

        if ($stat['size'] < self::MO_HEADER_SIZE) {
            throw new InvalidResourceException('MO stream content has an invalid format.');
        }
        $magic = unpack('V1', fread($stream, 4));
        $magic = hexdec(substr(dechex(current($magic)), -8));

        if (self::MO_LITTLE_ENDIAN_MAGIC == $magic) {
            $isBigEndian = false;
        } elseif (self::MO_BIG_ENDIAN_MAGIC == $magic) {
            $isBigEndian = true;
        } else {
            throw new InvalidResourceException('MO stream content has an invalid format.');
        }

        // formatRevision
        $this->readLong($stream, $isBigEndian);
        $count = $this->readLong($stream, $isBigEndian);
        $offsetId = $this->readLong($stream, $isBigEndian);
        $offsetTranslated = $this->readLong($stream, $isBigEndian);
        // sizeHashes

View on GitHub (pinned to ae9e8a51bc)