{"record":{"id":"d4fd37c156f22ae8","repo":"phalcon/cphalcon","slug":"error-opening-translation-file-file","errorCode":null,"errorMessage":"Error opening translation file '{file}'","messagePattern":"Error opening translation file '(.+?)'","errorType":"exception","errorClass":"Phalcon\\Translate\\Exceptions\\FileOpenError","httpStatus":null,"severity":"error","filePath":"phalcon/Translate/Adapter/Csv.zep","lineNumber":140,"sourceCode":"     * and skipped.\n     *\n     * @phpstan-param int<0, max> $length\n     *\n     * @throws FileOpenError\n     */\n    private function load(\n        string file,\n        int length,\n        string delimiter,\n        string enclosure,\n        string escape\n    ) -> void {\n        var data, fileHandler;\n\n        let fileHandler = this->phpFopen(file, \"rb\");\n\n        if unlikely typeof fileHandler !== \"resource\" {\n            throw new FileOpenError(file);\n        }\n\n        loop {\n            let data = this->phpFgetCsv(fileHandler, length, delimiter, enclosure, escape);\n\n            if data === false {\n                break;\n            }\n\n            if substr(data[0], 0, 1) === \"#\" || !isset data[1] {\n                continue;\n            }\n\n            let this->translate[data[0]] = data[1];\n        }\n\n        this->phpFclose(fileHandler);\n    }","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Translate/Adapter/Csv.zep#L122-L158","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Use an absolute path built from a known anchor: dirname(__DIR__) . '/messages/en.csv' or a config value.","Check is_readable($path) before instantiating and fail with a clear application error.","Verify the file is deployed and readable by the web/CLI user; check open_basedir when on restricted hosting."],"exampleFix":"// before\n$t = new Csv($factory, ['content' => 'messages/en.csv']); // relative, CWD-dependent\n\n// after\n$t = new Csv($factory, ['content' => dirname(__DIR__) . '/messages/en.csv']);","handlingStrategy":"validation","validationCode":"$file = $options['content'] ?? '';\nif (!is_string($file) || !is_readable($file)) {\n    throw new RuntimeException(\"Translation file not readable: {$file}\");\n}\n$t = new Csv($factory, $options);","typeGuard":null,"tryCatchPattern":"use Phalcon\\Translate\\Exceptions\\FileOpenError;\n\ntry {\n    $t = new Csv($factory, $options);\n} catch (FileOpenError $e) {\n    $logger->error($e->getMessage());\n    $t = new NativeArray($factory, ['content' => []]); // empty fallback dictionary\n}","preventionTips":["Always use absolute paths derived from a known anchor (dirname(__DIR__), project root config).","Include locale CSV files in the deploy artifact and verify permissions for the web/CLI user.","Check open_basedir restrictions on shared hosting before pointing at locale directories."],"tags":["phalcon","translate","csv","file-io","permissions","i18n"],"backgroundTag":"file-open-failed","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}