mikefarah/yq · error

only arrays are supported for unique

Error message

only arrays are supported for unique

What it means

The `unique` operator only works on sequence (array) nodes. If any candidate it is asked to deduplicate is a scalar or mapping, yq returns 'only arrays are supported for unique' and aborts the expression.

Source

Thrown at pkg/yqlib/operator_unique.go:26

)

func unique(d *dataTreeNavigator, context Context, _ *ExpressionNode) (Context, error) {
	selfExpression := &ExpressionNode{Operation: &Operation{OperationType: selfReferenceOpType}}
	uniqueByExpression := &ExpressionNode{Operation: &Operation{OperationType: uniqueByOpType}, RHS: selfExpression}
	return uniqueBy(d, context, uniqueByExpression)

}

func uniqueBy(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {

	log.Debugf("uniqueBy Operator")
	var results = list.New()

	for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
		candidate := el.Value.(*CandidateNode)

		if candidate.Kind != SequenceNode {
			return Context{}, fmt.Errorf("only arrays are supported for unique")
		}

		var newMatches = orderedmap.NewOrderedMap()
		for _, child := range candidate.Content {
			rhs, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(child), expressionNode.RHS)

			if err != nil {
				return Context{}, err
			}

			keyValue, err := getUniqueKeyValue(rhs)
			if err != nil {
				return Context{}, err
			}

			_, exists := newMatches.Get(keyValue)

			if !exists {

View on GitHub (pinned to 8b5af0694b)

Solutions

  1. Ensure the matched node is an array, e.g. `yq '.items | unique'` not `yq '.items[0] | unique'`
  2. Wrap with a type filter: `select(type == "seq") | unique` so non-arrays are skipped
  3. If you meant to deduplicate map keys/values, restructure: `to_entries | unique_by(.value) | from_entries`
  4. Fix the selector so it points at the sequence field of the document

Example fix

// before
yq 'unique' file.yaml
// after
yq '.items | unique' file.yaml
Defensive patterns

Strategy: type-guard

Validate before calling

// Check node kind before applying unique
if node.Kind != yaml.SequenceNode {
	return fmt.Errorf("unique requires an array, got kind %v", node.Kind)
}

Type guard

func isSequence(n *yaml.Node) bool { return n != nil && n.Kind == yaml.SequenceNode }

Try / catch

out, err := yqEval(".items | unique", doc)
if err != nil && strings.Contains(err.Error(), "only arrays are supported") {
	// handle scalar/map input case
}

Prevention

When it happens

Trigger: Running `yq 'unique'` (or `unique_by(...)`) on a document whose matched node is a map or scalar, e.g. `yq '.a' file.yaml` where a is `1`, or piping a single string into unique.

Common situations: Assuming the input is an array when the YAML file actually holds a map of items, applying unique at the document root of a scalar config value, or a path expression drifting to a non-sequence field after a schema change.

Related errors


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