{"record":{"id":"306f6099b7434e42","repo":"mikefarah/yq","slug":"only-arrays-are-supported-for-unique","errorCode":null,"errorMessage":"only arrays are supported for unique","messagePattern":"only arrays are supported for unique","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/yqlib/operator_unique.go","lineNumber":26,"sourceCode":")\n\nfunc unique(d *dataTreeNavigator, context Context, _ *ExpressionNode) (Context, error) {\n\tselfExpression := &ExpressionNode{Operation: &Operation{OperationType: selfReferenceOpType}}\n\tuniqueByExpression := &ExpressionNode{Operation: &Operation{OperationType: uniqueByOpType}, RHS: selfExpression}\n\treturn uniqueBy(d, context, uniqueByExpression)\n\n}\n\nfunc uniqueBy(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {\n\n\tlog.Debugf(\"uniqueBy Operator\")\n\tvar results = list.New()\n\n\tfor el := context.MatchingNodes.Front(); el != nil; el = el.Next() {\n\t\tcandidate := el.Value.(*CandidateNode)\n\n\t\tif candidate.Kind != SequenceNode {\n\t\t\treturn Context{}, fmt.Errorf(\"only arrays are supported for unique\")\n\t\t}\n\n\t\tvar newMatches = orderedmap.NewOrderedMap()\n\t\tfor _, child := range candidate.Content {\n\t\t\trhs, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(child), expressionNode.RHS)\n\n\t\t\tif err != nil {\n\t\t\t\treturn Context{}, err\n\t\t\t}\n\n\t\t\tkeyValue, err := getUniqueKeyValue(rhs)\n\t\t\tif err != nil {\n\t\t\t\treturn Context{}, err\n\t\t\t}\n\n\t\t\t_, exists := newMatches.Get(keyValue)\n\n\t\t\tif !exists {","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/mikefarah/yq/blob/8b5af0694bb82b41d4ae180fac9972029066f90a/pkg/yqlib/operator_unique.go#L8-L44","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nyq 'unique' file.yaml\n// after\nyq '.items | unique' file.yaml\n","handlingStrategy":"type-guard","validationCode":"// Check node kind before applying unique\nif node.Kind != yaml.SequenceNode {\n\treturn fmt.Errorf(\"unique requires an array, got kind %v\", node.Kind)\n}","typeGuard":"func isSequence(n *yaml.Node) bool { return n != nil && n.Kind == yaml.SequenceNode }","tryCatchPattern":"out, err := yqEval(\".items | unique\", doc)\nif err != nil && strings.Contains(err.Error(), \"only arrays are supported\") {\n\t// handle scalar/map input case\n}","preventionTips":["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"],"tags":["yaml","arrays","unique","type-error"],"backgroundTag":"operator-type-mismatch","analyzedSha":"8b5af0694bb82b41d4ae180fac9972029066f90a","analyzedAt":"2026-09-05T10:57:22.766Z","contentChangedAt":"2026-09-05T10:57:22.766Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}