hashicorp/nomad · error
%q: map key is not string: %s
Error message
%q: map key is not string: %s
What it means
helper/flatmap recursively flattens arbitrary Go values into a flat string-keyed map. When traversing a reflect.Map, all keys must be strings (after unwrapping interfaces); a non-string key type cannot be represented in the flat map, so flatten panics.
Source
Thrown at helper/flatmap/flatmap.go:65
output[prefix] = "nil"
case reflect.Pointer:
if primitiveOnly && enteredStruct {
return
}
e := v.Elem()
if !e.IsValid() {
output[prefix] = "nil"
}
flatten(prefix, e, primitiveOnly, enteredStruct, output)
case reflect.Map:
for _, k := range v.MapKeys() {
if k.Kind() == reflect.Interface {
k = k.Elem()
}
if k.Kind() != reflect.String {
panic(fmt.Sprintf("%q: map key is not string: %s", prefix, k))
}
flatten(getSubKeyPrefix(prefix, k.String()), v.MapIndex(k), primitiveOnly, enteredStruct, output)
}
case reflect.Struct:
if primitiveOnly && enteredStruct {
return
}
enteredStruct = true
t := v.Type()
for i := 0; i < v.NumField(); i++ {
name := t.Field(i).Name
val := v.Field(i)
if val.Kind() == reflect.Interface && !val.IsNil() {
val = val.Elem()
}
View on GitHub (pinned to 482b49bf1a)
Solutions
- Convert the map to map[string]interface{} (stringify keys) before passing the value to Flatten/Diff
- Change the containing struct so map keys are strings
- Stringify keys at the boundary with a helper like fmt.Sprint(k) into a new map
Example fix
// before
m := map[int]string{1: "a"}
out := flatmap.Flatten(m) // panics
// after
m2 := map[string]interface{}{"1": "a"}
out := flatmap.Flatten(m2) Defensive patterns
Strategy: validation
Validate before calling
func hasStringKeys(v reflect.Value) bool {
if v.Kind() != reflect.Map { return true }
for _, k := range v.MapKeys() {
if k.Kind() == reflect.Interface { k = k.Elem() }
if k.Kind() != reflect.String { return false }
}
return true
}
Type guard
func flattenSafe(v interface{}) (m map[string]string, ok bool) {
defer func() {
if r := recover(); r != nil { ok = false; m = nil }
}()
m = flatmap.Flatten(v)
return m, true
}
Try / catch
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("flatmap: %v", r)
}
}() Prevention
- Use string map keys in structs destined for Flatten/Diff
- Validate payloads for non-string map keys before diffing
- Keep flatmap inputs limited to API-serialization-friendly types
When it happens
Trigger: Calling flatmap.Flatten or flatmap.Diff on a struct/variable payload that contains a map with non-string keys (e.g. map[int]string, map[uuid.UUID]...).
Common situations: Task/group payloads or job specs containing maps keyed by integers or custom types passed into the flatmap-based diffing code; user structs handed to Nomad's templating/diff utilities with typed map keys.
Related errors
- prefix %q; unsupported type %v
- invalid acl policy: %v
- invalid type for node variable: %T
- key %q has invalid type %T
- failed to decode key %q to string
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/f14eca0f6e7d7957.
Report an issue: GitHub.