glanceapp/glance · error
orderedMap: expected mapping node, got %d
Error message
orderedMap: expected mapping node, got %d
What it means
orderedYAMLMap's custom UnmarshalYAML rejects any YAML node that is not a mapping. The type preserves key order for structures like widget maps where order matters; feeding it a scalar, sequence, or document node fails with the node's Kind number (0=document, 2=sequence, 4=scalar, 8=alias per go-yaml).
Source
Thrown at internal/glance/config.go:604
data: make(map[K]V, len(self.data)+len(other.data)),
}
merged.keys = append(merged.keys, self.keys...)
maps.Copy(merged.data, self.data)
for _, key := range other.keys {
if _, exists := self.data[key]; !exists {
merged.keys = append(merged.keys, key)
}
}
maps.Copy(merged.data, other.data)
return merged
}
func (om *orderedYAMLMap[K, V]) UnmarshalYAML(node *yaml.Node) error {
if node.Kind != yaml.MappingNode {
return fmt.Errorf("orderedMap: expected mapping node, got %d", node.Kind)
}
if len(node.Content)%2 != 0 {
return fmt.Errorf("orderedMap: expected even number of content items, got %d", len(node.Content))
}
om.keys = make([]K, len(node.Content)/2)
om.data = make(map[K]V, len(node.Content)/2)
for i := 0; i < len(node.Content); i += 2 {
keyNode := node.Content[i]
valueNode := node.Content[i+1]
var key K
if err := keyNode.Decode(&key); err != nil {
return fmt.Errorf("orderedMap: decoding key: %v", err)
}
View on GitHub (pinned to 91324e8de7)
Solutions
- Rewrite the YAML at that key as a mapping (key: value lines), not a list or scalar
- Compare with the docs for the specific field — if examples show named keys, use named keys
- If Kind is 2, you wrote a sequence; if 4, a scalar — convert to a block mapping
Example fix
# before (list where mapping expected)
groups:
- group-a:
widgets: []
# after (mapping)
groups:
group-a:
widgets: [] Defensive patterns
Strategy: type-guard
Validate before calling
// Before unmarshal, assert the node shape at the offending key: var probe yaml.Node _ = yaml.Unmarshal(raw, &probe) // walk to the field and check probe.Kind == yaml.MappingNode before full decode
Type guard
func isMappingNode(n *yaml.Node) bool {
return n != nil && n.Kind == yaml.MappingNode
} Try / catch
if err := yaml.Unmarshal(raw, &cfg); err != nil {
if strings.Contains(err.Error(), "orderedMap: expected mapping node") {
// locate the non-mapping key in the YAML and rewrite it as key: value pairs
log.Printf("config shape error: %v", err)
}
} Prevention
- Match the documented YAML shape exactly for map-typed fields (no '- ' list syntax)
- Use an editor with a YAML schema to catch shape mismatches live
When it happens
Trigger: Using an ordered-map-backed config field (e.g. a widget's keyed settings) but writing it as a YAML list or a plain string instead of key: value pairs. E.g. 'groups:' followed by '- name: x' where a map is expected.
Common situations: Confusing list syntax (- item) with mapping syntax for fields documented as maps; pasting example YAML of the wrong shape; putting a quoted string where a block mapping is required.
Related errors
- %s widget: %v
- recursion depth limit of %d reached
- no pages configured
- user has no name
- page %d has no name
AI-assisted analysis of glanceapp/glance@91324e8de7 (2026-08-15).
Data as JSON: /api/errors/c5f87139747a1ba0.
Report an issue: GitHub.