stalwartlabs/stalwart · error

Missing: {}

Error message

Missing: {}

What it means

While emitting the generated locale constants, generate_locale_code iterates every translation key and fetches each language's value; a panic here means a key exists in the locales map but has no entry for the language currently being generated. The panic message names the offending key. In practice this indicates an inconsistent YAML where a top-level key defines no translation lines at all, so the key exists with an empty per-language map and every language misses it.

Source

Thrown at crates/common/build.rs:180

    let mut languages = std::collections::HashSet::new();
    for translations in locales.values() {
        for lang in translations.keys() {
            languages.insert(lang.clone());
        }
    }

    for lang in &languages {
        code.push_str(&format!(
            "pub static {}_LOCALES: Locale = Locale {{\n",
            const_name(lang)
        ));
        code.push_str(&format!("    name: {lang:?},\n"));
        code.push_str(&format!("    direction: {:?},\n", direction(lang)));

        for (key, translations) in locales {
            let value = translations
                .get(lang)
                .unwrap_or_else(|| panic!("Missing: {}", key));
            if plural.contains(key) {
                code.push_str(&format!("    {key}: {},\n", plural_forms_literal(value)));
            } else {
                code.push_str(&format!("    {key}: {value:?},\n"));
            }
        }

        code.push_str("};\n\n");
    }

    let mut sorted: Vec<&String> = languages.iter().collect();
    sorted.sort_unstable();
    code.push_str(&format!(
        "pub static ALL_LOCALES: [&Locale; {}] = [\n",
        sorted.len()
    ));
    for lang in &sorted {
        code.push_str(&format!("    &{}_LOCALES,\n", const_name(lang)));

View on GitHub (pinned to e962003857)

Solutions

  1. Add translation entries for the named key in i18n.yml for every supported language (at minimum the language cited in the build output).
  2. If the key is unused, delete its header line entirely so the key is not registered.
  3. Check indentation: language lines must be indented under the key header to be parsed as translations.

Example fix

# before
key.new:
# after
key.new:
  en: Some text
  de: Ein Text
Defensive patterns

Strategy: validation

Validate before calling

// ensure every key has a value for every language before generation
for (key, translations) in &locales {
    for lang in all_languages {
        assert!(translations.contains_key(lang), "key {key} missing translation for {lang}");
    }
}

Prevention

When it happens

Trigger: A key header line in i18n.yml (e.g. `key.name:`) with no indented per-language entries under it, combined with another language having at least one translation — the empty map fails `.get(lang)` for every language during generation after plural_keys validation passes.

Common situations: A developer creates a placeholder key and forgets to fill in translations; an edit deletes all language lines under a key but leaves the header; a merge dropped indented lines while keeping the key.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of stalwartlabs/stalwart@e962003857 (2026-09-06). Data as JSON: /api/errors/67a4e265d6f1603c. Report an issue: GitHub.