knadh/listmonk · critical
error reading lang file: %s: %v
Error message
error reading lang file: %s: %v
What it means
getI18nLangList reads embedded i18n language JSON files from the stuffbin virtual filesystem. When fs.Get fails to retrieve a listed language file, it wraps the failure with the filename and underlying error. Because language files are embedded at build time, this almost always indicates a broken build/embed rather than runtime user error.
Source
Thrown at cmd/i18n.go:54
return echo.NewHTTPError(http.StatusBadRequest, "Unknown language.")
}
return c.JSON(http.StatusOK, okResp{json.RawMessage(i.JSON())})
}
// getI18nLangList returns the list of available i18n languages.
func getI18nLangList(fs stuffbin.FileSystem) ([]i18nLang, error) {
list, err := fs.Glob("/i18n/*.json")
if err != nil {
return nil, err
}
// Read language JSON files from the fs.
var out []i18nLang
for _, l := range list {
b, err := fs.Get(l)
if err != nil {
return out, fmt.Errorf("error reading lang file: %s: %v", l, err)
}
var r i18nLangRaw
if err := json.Unmarshal(b.ReadBytes(), &r); err != nil {
return out, fmt.Errorf("error parsing lang file: %s: %v", l, err)
}
out = append(out, i18nLang(r))
}
// Sort by language code.
sort.SliceStable(out, func(i, j int) bool {
return out[i].Code < out[j].Code
})
return out, nil
}
View on GitHub (pinned to 670c01717d)
Solutions
- Rebuild the binary using the project's build process (make build) so i18n assets are embedded via stuffbin.
- If running from source, use `go run .` which handles asset embedding per the README.
- Verify the binary contains the i18n files (stuffbin listing or build logs).
- If you added a custom language, ensure it is included in the embedding step.
Example fix
// before $ go build -o listmonk # assets not embedded // after $ make build # embeds i18n/static via stuffbin
Defensive patterns
Strategy: try-catch
Validate before calling
// At deploy time: confirm assets are embedded
out, _ := exec.Command("strings", binaryPath).Output()
if !strings.Contains(string(out), "i18n/en.json") {
log.Fatal("binary missing embedded i18n assets; rebuild with make build")
} Try / catch
langs, err := getI18nLangList(fs)
if err != nil {
log.Fatalf("i18n init failed (embedded assets missing?): %v", err)
} Prevention
- Always build via make build so stuffbin embeds assets.
- Never deploy a bare `go build` binary.
- Use `go run .` when running from source.
- Add a smoke test that lists embedded /i18n files on startup.
When it happens
Trigger: GetServerConfig → getI18nLangList iterates the embedded /i18n/*.json list and fs.Get(l) fails — the file is missing from the binary (built without listmonk's stuffbin packing, e.g. plain `go build` without asset embedding) or the fs mount is misconfigured.
Common situations: Building the binary without the stuffbin embedding step so static/i18n resources are absent; deploying a partially built binary; forks adding a language file to the list without packaging it.
Related errors
- error reading default i18n language file: %s: %v
- error parsing lang file: %s: %v
- 'email' column not found
- subscribers.invalidEmail
- token was not found or has expired
AI-assisted analysis of knadh/listmonk@670c01717d (2026-09-01).
Data as JSON: /api/errors/9b62840d02630747.
Report an issue: GitHub.