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
- Ensure the matched node is an array, e.g. `yq '.items | unique'` not `yq '.items[0] | unique'`
- Wrap with a type filter: `select(type == "seq") | unique` so non-arrays are skipped
- If you meant to deduplicate map keys/values, restructure: `to_entries | unique_by(.value) | from_entries`
- 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
- Select the array field explicitly before calling unique
- Add `select(type == "seq")` guards in expressions
- Verify document structure with `. | type` when unsure
- Update expressions after schema changes that turn arrays into maps
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
- system operator: command must be a string scalar
- cannot convert node at path %v of tag %v to number
- yaml node has no content
- orderedMap: invalid yaml node
- INI encoder supports only MappingNode at the root level, got
AI-assisted analysis of mikefarah/yq@8b5af0694b (2026-09-05).
Data as JSON: /api/errors/306f6099b7434e42.
Report an issue: GitHub.