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

  1. Ensure the input is an array: wrap scalars with '[.x]' or use 'collect': '[.tags] | join(",")'.
  2. For maps, convert first: '.obj | to_entries | map(.value) | join(",")' or '.obj | keys | join(",")'.
  3. 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

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


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