mikefarah/yq · error

maps not yet supported for subtraction

Error message

maps not yet supported for subtraction

What it means

The subtract operator in operator_subtract.go supports arrays (set difference), scalars (numbers, and string/element removal variants), but not mappings. Subtracting anything from a map node immediately returns 'maps not yet supported for subtraction' — this is an explicit unimplemented-feature guard, not a data error.

Source

Thrown at pkg/yqlib/operator_subtract.go:52

			}
		}
		if shouldInclude {
			newLHSArray = append(newLHSArray, lhs.Content[lindex])
		}
	}
	return newLHSArray
}

func subtract(_ *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
	if lhs.Tag == "!!null" {
		return lhs.CopyAsReplacement(rhs), nil
	}

	target := lhs.CopyWithoutContent()

	switch lhs.Kind {
	case MappingNode:
		return nil, fmt.Errorf("maps not yet supported for subtraction")
	case SequenceNode:
		if rhs.Kind != SequenceNode {
			return nil, fmt.Errorf("%v (%v) cannot be subtracted from %v", rhs.Tag, rhs.GetNicePath(), lhs.Tag)
		}
		target.Content = subtractArray(lhs, rhs)
	case ScalarNode:
		if rhs.Kind != ScalarNode {
			return nil, fmt.Errorf("%v (%v) cannot be subtracted from %v", rhs.Tag, rhs.GetNicePath(), lhs.Tag)
		}
		target.Kind = ScalarNode
		target.Style = lhs.Style
		if err := subtractScalars(context, target, lhs, rhs); err != nil {
			return nil, err
		}
	}

	return target, nil
}

View on GitHub (pinned to 8b5af0694b)

Solutions

  1. Use 'del()' to remove keys from a map: 'del(.obj.key1, .obj.key2)' or 'del(.obj[] | select(...))' style paths.
  2. To remove a set of keys dynamically: 'del(.obj.[(.keys | .[])])' or '.obj | del(.[] | select(.key in $keys))' variants depending on the desired semantics.
  3. If set-difference was intended, ensure both operands are arrays/sequences: '[.list1[]] - [.list2[]]'.

Example fix

// before (fails: maps unsupported)
yq '.env - {DEBUG: true}' config.yaml

// after: remove specific keys
yq 'del(.env.DEBUG)' config.yaml
Defensive patterns

Strategy: validation

Validate before calling

KIND=$(yq '.a | kind' file.yaml); [ "$KIND" != "map" ] || { echo "subtraction not supported for maps; use del()"; exit 1; }

Type guard

// in yq: select(kind != "map") | . - other
function isMapNode(node) { return node && node.kind === 'map'; }

Try / catch

out=$(yq '.env - {DEBUG: true}' file.yaml 2>&1) || { echo "map subtraction unsupported: $out"; out="$(yq 'del(.env.DEBUG)' file.yaml)"; }

Prevention

When it happens

Trigger: Expressions like '.myMap - {a: 1}', '.config - ["key1"]' where .config is a mapping, or '.obj - .other' when either operand evaluates to a MappingNode. Also hit via arithmetic paths like '(.a + 1) - .map'.

Common situations: Users coming from jq expecting object subtraction/key removal; trying to delete keys from a map with '-' instead of 'del()'; Kubernetes config patching attempts that subtract whole objects.

Related errors


AI-assisted analysis of mikefarah/yq@8b5af0694b (2026-09-05). Data as JSON: /api/errors/e983c42017852d1e. Report an issue: GitHub.