mikefarah/yq · error
cannot join with %v, can only join arrays of scalars
Error message
cannot join with %v, can only join arrays of scalars
What it means
The join operator ('join(sep)') in operator_strings.go only accepts sequence (array) nodes; it builds a single string from the array's scalar elements. If the node being joined has any other kind — a map, a scalar, or null — yq refuses with this message, reporting the node's tag.
Source
Thrown at pkg/yqlib/operator_strings.go:509
func joinStringOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
log.Debugf("joinStringOperator")
joinStr := ""
rhs, err := d.GetMatchingNodes(context.ReadOnlyClone(), expressionNode.RHS)
if err != nil {
return Context{}, err
}
if rhs.MatchingNodes.Front() != nil {
joinStr = rhs.MatchingNodes.Front().Value.(*CandidateNode).Value
}
var results = list.New()
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
node := el.Value.(*CandidateNode)
if node.Kind != SequenceNode {
return Context{}, fmt.Errorf("cannot join with %v, can only join arrays of scalars", node.Tag)
}
result := node.CreateReplacement(join(node.Content, joinStr))
results.PushBack(result)
}
return context.ChildContext(results), nil
}
func join(content []*CandidateNode, joinStr string) (Kind, string, string) {
var stringsToJoin []string
for _, node := range content {
str := node.Value
if node.Tag == "!!null" {
str = ""
}
stringsToJoin = append(stringsToJoin, str)
}
View on GitHub (pinned to 8b5af0694b)
Solutions
- Ensure the input is an array: wrap scalars with '[.x]' or use 'collect': '[.tags] | join(",")'.
- For maps, convert first: '.obj | to_entries | map(.value) | join(",")' or '.obj | keys | join(",")'.
- Filter out nulls before joining: 'map(select(. != null)) | join(",")'.
Example fix
// before (fails: .tags may be a scalar)
yq '.tags | join(",")' config.yaml
// after
yq '[.tags] | join(",")' config.yaml Defensive patterns
Strategy: validation
Validate before calling
yq '.tags | type' file.yaml # must be '!!seq' before join
// script check:
T=$(yq '.tags | type' file.yaml); [ "$T" = "!!seq" ] || { echo "join needs an array, got $T"; exit 1; } Type guard
// in yq expression: select(type == "!!seq") | join(",")
function isSequenceNode(node) { return node && node.kind === 'sequence'; } Try / catch
if ! out=$(yq '.tags | join(",")' file.yaml 2>&1); then echo "join failed: $out"; out="$(yq '[.tags] | join(",")' file.yaml)"; fi # fallback to wrapping scalar in array Prevention
- Wrap possibly-scalar values in '[...]' or use 'collect' before join.
- Convert maps with 'to_entries'/'keys' before joining.
- Strip nulls with 'map(select(. != null))' before joining heterogeneous data.
When it happens
Trigger: Calling 'join(",")' on a node that is not an array: e.g. '.tags | join(",")' when .tags is a single string, a map (object), or null; or piping a mapping like '{a: 1, b: 2} | join(",")'.
Common situations: Config files where a field is sometimes a single scalar and sometimes a list; users trying to join object keys/values without converting first (forgot 'keys' or 'to_entries | map(.value)'); empty/null fields produced by 'select' filters feeding into join.
Related errors
- %v (%v) cannot be subtracted from %v
- %v (%v) cannot be subtracted from %v
- %v cannot check contained in %v
- from entries only runs against arrays
- cannot substitute with %v, can only substitute strings. Hint
AI-assisted analysis of mikefarah/yq@8b5af0694b (2026-09-05).
Data as JSON: /api/errors/4a0a9c38c45d011c.
Report an issue: GitHub.