{"record":{"id":"8c69218c32567f74","repo":"coder/code-server","slug":"failed-to-load-custom-strings-from-filepath","errorCode":null,"errorMessage":"Failed to load custom strings from ${filePath}: ${error instanceof Error ? error.message : String(error)}","messagePattern":"Failed to load custom strings from (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/node/i18n/index.ts","lineNumber":43,"sourceCode":"}\n\nexport async function loadCustomStrings(filePath: string): Promise<void> {\n  try {\n    // Read custom strings from file path only\n    const fileContent = await fs.readFile(filePath, \"utf8\")\n    const customStringsData = JSON.parse(fileContent)\n\n    // User-provided strings override all languages.\n    Object.keys(defaultResources).forEach((locale) => {\n      i18next.addResourceBundle(locale, \"translation\", customStringsData)\n    })\n  } catch (error) {\n    if (error && typeof error === \"object\" && \"code\" in error && error.code === \"ENOENT\") {\n      throw new Error(`Custom strings file not found: ${filePath}\\nPlease ensure the file exists and is readable.`)\n    } else if (error instanceof SyntaxError) {\n      throw new Error(`Invalid JSON in custom strings file: ${filePath}\\n${error.message}`)\n    } else {\n      throw new Error(\n        `Failed to load custom strings from ${filePath}: ${error instanceof Error ? error.message : String(error)}`,\n      )\n    }\n  }\n}\n\ninit({\n  lng: \"en\",\n  fallbackLng: \"en\", // language to use if translations in user language are not available.\n  returnNull: false,\n  lowerCaseLng: true,\n  debug: process.env.NODE_ENV === \"development\",\n  resources: defaultResources,\n})\n\nexport default i18next\n","sourceCodeStart":25,"sourceCodeEnd":60,"githubUrl":"https://github.com/coder/code-server/blob/51f90a376b42e217b38937410fe2855e0c1db87e/src/node/i18n/index.ts#L25-L60","documentation":"The final else branch of loadCustomStrings catches any error that is neither ENOENT nor SyntaxError (e.g. EACCES permission denied, EISDIR for a directory, or a thrown non-Error). It rethrows a generic `Failed to load custom strings from <path>` with the underlying message, preserving the cause text.","triggerScenarios":"The --i18n path exists and parses but cannot be read due to permissions (EACCES), is a directory (EISDIR), or hits a filesystem error (disk, mount).","commonSituations":"Containers where the file is owned by root but code-server runs as a non-root user; pointing --i18n at a directory by mistake; read-only filesystems.","solutions":["Check permissions: `ls -l /path/strings.json` and ensure the code-server user has read access","Confirm the path is a file, not a directory","In containers, set the file's owner/group or chmod it to be world-readable if appropriate"],"exampleFix":"# before: file owned by root, code-server runs as 'coder'\n$ ls -l strings.json\n-rw------- 1 root root ... strings.json\n\n# after\nchown coder:coder strings.json\n# or\nchmod a+r strings.json","handlingStrategy":"try-catch","validationCode":"import fs from \"fs/promises\"\nasync function assertReadableFile(path: string): Promise<void> {\n  const stat = await fs.stat(path)\n  if (!stat.isFile()) throw new Error(`${path} is not a regular file`)\n  await fs.access(path, fs.constants.R_OK)\n}","typeGuard":"function isFsError(e: unknown): e is NodeJS.ErrnoException {\n  return typeof e === \"object\" && e !== null && typeof (e as NodeJS.ErrnoException).code === \"string\"\n}","tryCatchPattern":"try {\n  await loadCustomStrings(args.i18n)\n} catch (e) {\n  const code = (e as NodeJS.ErrnoException).code\n  if (code === \"EACCES\") console.error(`Permission denied reading ${args.i18n}`)\n  else if (code === \"EISDIR\") console.error(`${args.i18n} is a directory`)\n  else throw e\n}","preventionTips":["Set the strings file's owner/group to the code-server runtime user","Document the expected file permissions in the deploy guide","Validate the path is a file (not a directory) at deploy time"],"tags":["i18n","filesystem","permissions","configuration","startup"],"backgroundTag":null,"analyzedSha":"51f90a376b42e217b38937410fe2855e0c1db87e","analyzedAt":"2026-08-12T11:27:34.273Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}