knadh/listmonk · critical

error reading default i18n language file: %s: %v

Error message

error reading default i18n language file: %s: %v

What it means

getI18nLang initializes the i18n system by first reading the default English pack (/i18n/en.json) from the stuffbin filesystem, since other languages fall back to it. If that read fails it wraps the error with the 'en' code. A missing default pack breaks i18n initialization, though per the surrounding comment the app may log a warning instead of halting.

Source

Thrown at cmd/i18n.go:80

		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
}

// The bool indicates whether the specified language could be loaded. If it couldn't
// be, the app shouldn't halt but throw a warning.
func getI18nLang(lang string, fs stuffbin.FileSystem) (*i18n.I18n, bool, error) {
	const def = "en"

	b, err := fs.Read(fmt.Sprintf("/i18n/%s.json", def))
	if err != nil {
		return nil, false, fmt.Errorf("error reading default i18n language file: %s: %v", def, err)
	}

	// Initialize with the default language.
	i, err := i18n.New(b)
	if err != nil {
		return nil, false, fmt.Errorf("error unmarshalling i18n language: %s: %v", lang, err)
	}

	// Load the selected language on top of it.
	b, err = fs.Read(fmt.Sprintf("/i18n/%s.json", lang))
	if err != nil {
		return i, true, fmt.Errorf("error reading i18n language file: %s: %v", lang, err)
	}
	if err := i.Load(b); err != nil {
		return i, true, fmt.Errorf("error loading i18n language file: %s: %v", lang, err)
	}

	return i, true, nil

View on GitHub (pinned to 670c01717d)

Solutions

  1. Rebuild with the standard build pipeline (make build) so /i18n/en.json is embedded via stuffbin.
  2. Ensure i18n/en.json exists in the repo and is included in the packaging list.
  3. If running from source, use `go run .` per the README so assets are packed automatically.
  4. Keep 'en' present even when localizing — it is the required fallback default.

Example fix

// before
$ rm i18n/en.json && make build
// after
$ git checkout -- i18n/en.json && make build
Defensive patterns

Strategy: try-catch

Validate before calling

b, err := fs.Read("/i18n/en.json")
if err != nil {
    log.Fatal("default language pack missing; rebuild binary with embedded assets")
}

Try / catch

i, warn, err := getI18nLang(lang, fs)
if err != nil {
    log.Printf("i18n unavailable, continuing without translations: %v", err)
    return nil, warn, nil // app continues, per library's non-fatal policy
}

Prevention

When it happens

Trigger: initI18n or GetI18nLang → getI18nLang calls fs.Read("/i18n/en.json") and the file is absent from the embedded filesystem — typically a binary built without stuffbin asset embedding, or a renamed/removed en.json in a fork.

Common situations: Deploying a bare `go build` binary without embedded assets; trimming i18n files and accidentally deleting en.json; renaming language files without keeping 'en' as the default.

Related errors


AI-assisted analysis of knadh/listmonk@670c01717d (2026-09-01). Data as JSON: /api/errors/b00b6d38cab7c445. Report an issue: GitHub.