phalcon/cphalcon · error · Phalcon\Translate\Exceptions\FileOpenError

Error opening translation file '{file}'

Error message

Error opening translation file '{file}'

What it means

Csv::load() opens the file from options['content'] via fopen($file, 'rb'); when fopen() fails (returns false instead of a resource) the adapter throws Phalcon\Translate\Exceptions\FileOpenError with the path in the message (phalcon/Translate/Adapter/Csv.zep:140). This happens during construction, before any translation is requested.

Source

Thrown at phalcon/Translate/Adapter/Csv.zep:140

     * and skipped.
     *
     * @phpstan-param int<0, max> $length
     *
     * @throws FileOpenError
     */
    private function load(
        string file,
        int length,
        string delimiter,
        string enclosure,
        string escape
    ) -> void {
        var data, fileHandler;

        let fileHandler = this->phpFopen(file, "rb");

        if unlikely typeof fileHandler !== "resource" {
            throw new FileOpenError(file);
        }

        loop {
            let data = this->phpFgetCsv(fileHandler, length, delimiter, enclosure, escape);

            if data === false {
                break;
            }

            if substr(data[0], 0, 1) === "#" || !isset data[1] {
                continue;
            }

            let this->translate[data[0]] = data[1];
        }

        this->phpFclose(fileHandler);
    }

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Use an absolute path built from a known anchor: dirname(__DIR__) . '/messages/en.csv' or a config value.
  2. Check is_readable($path) before instantiating and fail with a clear application error.
  3. Verify the file is deployed and readable by the web/CLI user; check open_basedir when on restricted hosting.

Example fix

// before
$t = new Csv($factory, ['content' => 'messages/en.csv']); // relative, CWD-dependent

// after
$t = new Csv($factory, ['content' => dirname(__DIR__) . '/messages/en.csv']);
Defensive patterns

Strategy: validation

Validate before calling

$file = $options['content'] ?? '';
if (!is_string($file) || !is_readable($file)) {
    throw new RuntimeException("Translation file not readable: {$file}");
}
$t = new Csv($factory, $options);

Try / catch

use Phalcon\Translate\Exceptions\FileOpenError;

try {
    $t = new Csv($factory, $options);
} catch (FileOpenError $e) {
    $logger->error($e->getMessage());
    $t = new NativeArray($factory, ['content' => []]); // empty fallback dictionary
}

Prevention

When it happens

Trigger: Constructing Csv with a nonexistent or misspelled path, a file the PHP process cannot read (permissions), a path blocked by open_basedir, or a relative path resolved from an unexpected CWD (CLI worker vs web).

Common situations: Relative paths that work under FPM but break in CLI/cron/workers; deployment pipelines that skip the locale CSV files; case-sensitivity differences between dev (macOS/Windows) and prod Linux; shared-hosting open_basedir restrictions.

Related errors


AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21). Data as JSON: /api/errors/d4fd37c156f22ae8. Report an issue: GitHub.