coder/code-server · error · Error
Failed to load custom strings from ${filePath}: ${error inst
Error message
Failed to load custom strings from ${filePath}: ${error instanceof Error ? error.message : String(error)} What it means
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.
Source
Thrown at src/node/i18n/index.ts:43
}
export async function loadCustomStrings(filePath: string): Promise<void> {
try {
// Read custom strings from file path only
const fileContent = await fs.readFile(filePath, "utf8")
const customStringsData = JSON.parse(fileContent)
// User-provided strings override all languages.
Object.keys(defaultResources).forEach((locale) => {
i18next.addResourceBundle(locale, "translation", customStringsData)
})
} catch (error) {
if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
throw new Error(`Custom strings file not found: ${filePath}\nPlease ensure the file exists and is readable.`)
} else if (error instanceof SyntaxError) {
throw new Error(`Invalid JSON in custom strings file: ${filePath}\n${error.message}`)
} else {
throw new Error(
`Failed to load custom strings from ${filePath}: ${error instanceof Error ? error.message : String(error)}`,
)
}
}
}
init({
lng: "en",
fallbackLng: "en", // language to use if translations in user language are not available.
returnNull: false,
lowerCaseLng: true,
debug: process.env.NODE_ENV === "development",
resources: defaultResources,
})
export default i18next
View on GitHub (pinned to 51f90a376b)
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
Example fix
# before: file owned by root, code-server runs as 'coder' $ ls -l strings.json -rw------- 1 root root ... strings.json # after chown coder:coder strings.json # or chmod a+r strings.json
Defensive patterns
Strategy: try-catch
Validate before calling
import fs from "fs/promises"
async function assertReadableFile(path: string): Promise<void> {
const stat = await fs.stat(path)
if (!stat.isFile()) throw new Error(`${path} is not a regular file`)
await fs.access(path, fs.constants.R_OK)
} Type guard
function isFsError(e: unknown): e is NodeJS.ErrnoException {
return typeof e === "object" && e !== null && typeof (e as NodeJS.ErrnoException).code === "string"
} Try / catch
try {
await loadCustomStrings(args.i18n)
} catch (e) {
const code = (e as NodeJS.ErrnoException).code
if (code === "EACCES") console.error(`Permission denied reading ${args.i18n}`)
else if (code === "EISDIR") console.error(`${args.i18n} is a directory`)
else throw e
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Custom strings file not found: ${filePath}\nPlease ensure th
- Invalid JSON in custom strings file: ${filePath}\n${error.me
- invalid config: ${config}
- Please pass in a password via the config file or environment
- --password can only be set in the config file or passed in v
AI-assisted analysis of coder/code-server@51f90a376b (2026-08-12).
Data as JSON: /api/errors/8c69218c32567f74.
Report an issue: GitHub.