kataras/iris · error

%s:%s unexpected type of %T as value

Error message

%s:%s unexpected type of %T as value

What it means

Each value in a translation Map must be either a string (message) or another Map (section). Any other Go type (int, bool, slice, struct, nil) is rejected with this error identifying the locale, key and offending type via %T.

Source

Thrown at i18n/internal/locale.go:76

		if isPlural {
			k = key
		} else if !isRoot {
			k = key + "." + k
		}

		switch value := v.(type) {
		case string:
			if err := loc.setString(c, k, value, vars, form); err != nil {
				return fmt.Errorf("%s:%s parse string: %w", loc.ID, key, err)
			}
		case Map:
			// fmt.Printf("%s is map\n", fullKey)
			if err := loc.setMap(c, k, value); err != nil {
				return fmt.Errorf("%s:%s parse map: %w", loc.ID, key, err)
			}

		default:
			return fmt.Errorf("%s:%s unexpected type of %T as value", loc.ID, key, value)
		}
	}

	return nil
}

func (loc *Locale) setString(c *Catalog, key string, value string, vars []Var, form PluralForm) (err error) {
	isPlural := form != nil

	// fmt.Printf("setStringVars: %s=%s\n", key, value)
	msgs, vars := makeSelectfVars(value, vars, isPlural)
	msgs = append(msgs, catalog.String(value))

	m := &Message{
		Locale: loc,
		Key:    key,
		Value:  value,
		Vars:   vars,

View on GitHub (pinned to 7bedaf55a0)

Solutions

  1. Convert all leaf values to string (or nested Map) before storing — fmt.Sprint or explicit quoting in YAML/JSON
  2. Quote numeric/boolean values in locale files so decoders produce strings
  3. Validate the kv structure with a recursive check before calling Store/Load
  4. Fix data sources (DB/config) to emit strings for translation values

Example fix

// before (values.yml)
max_items: 5
enabled: yes
// after
max_items: "5"
enabled: "yes"
Defensive patterns

Strategy: type-guard

Validate before calling

func stringsOnly(m map[string]any) error {
    for k, v := range m {
        switch t := v.(type) {
        case string:
        case map[string]any:
            if err := stringsOnly(t); err != nil { return err }
        default:
            return fmt.Errorf("key %s: unsupported type %T", k, v)
        }
    }
    return nil
}

Type guard

func isTranslatableValue(v any) bool {
    switch v.(type) {
    case string, map[string]any:
        return true
    default:
        return false
    }
}

Try / catch

if err := loc.Load(c, kv); err != nil {
    if strings.Contains(err.Error(), "unexpected type") {
        log.Printf("non-string translation value: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: Storing kv maps where values came from an untyped source: JSON numbers/booleans, YAML scalars decoded as int/bool, or slices where the i18n API expects string or Map — e.g. count: 5 or items: [a, b] in a locale file.

Common situations: YAML locale files with unquoted numbers or booleans decoded to non-string types; JSON translation files with numeric values; dynamically generated maps fed into catalog.Store from configs or databases with non-string columns.

Related errors


AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30). Data as JSON: /api/errors/3f6441e52760ef32. Report an issue: GitHub.