mikefarah/yq · error

reduce must be given a block, got %v instead

Error message

reduce must be given a block, got %v instead

What it means

Along with a variable assignment on the left, `reduce` expects the right-hand side of its expression to be a block operation (the `(init; update)` body). This error fires when the RHS is some other operation type, meaning the reduce body was malformed or omitted. yq throws it because the block carries the accumulator initialiser and update expression.

Source

Thrown at pkg/yqlib/operator_reduce.go:21

import (
	"container/list"
	"fmt"
)

func reduceOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
	log.Debugf("reduceOp")
	//.a as $var reduce (0; . + $var)
	//lhs is the assignment operator
	//rhs is the reduce block
	// '.' refers to the current accumulator, initialised to 0
	// $var references a single element from the .a

	//ensure lhs is actually an assignment
	//and rhs is a block (empty)
	if expressionNode.LHS.Operation.OperationType != assignVariableOpType {
		return Context{}, fmt.Errorf("reduce must be given a variables assignment, got %v instead", expressionNode.LHS.Operation.OperationType.Type)
	} else if expressionNode.RHS.Operation.OperationType != blockOpType {
		return Context{}, fmt.Errorf("reduce must be given a block, got %v instead", expressionNode.RHS.Operation.OperationType.Type)
	}

	arrayExpNode := expressionNode.LHS.LHS
	array, err := d.GetMatchingNodes(context, arrayExpNode)

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

	variableName := expressionNode.LHS.RHS.Operation.StringValue

	initExp := expressionNode.RHS.LHS

	accum, err := d.GetMatchingNodes(context, initExp)
	if err != nil {
		return Context{}, err
	}

View on GitHub (pinned to 8b5af0694b)

Solutions

  1. Supply the parenthesised block: `reduce .a[] as $x (0; . + $x)`.
  2. Make sure there is no pipe operator between `as $x` and the `(init; update)` block.
  3. Include both initialiser and update separated by `;` inside the parentheses.
  4. If you only need a sum/aggregation, verify reduce is the right operator versus `add` or `sum`.

Example fix

// before
yq 'reduce .a[] as $x 0' file.yml
// after
yq 'reduce .a[] as $x (0; . + $x)' file.yml
Defensive patterns

Strategy: try-catch

Validate before calling

echo "$expr" | grep -Eq 'as \\$[a-zA-Z_]+ \\([^)]*;[^)]*\\)' || echo "reduce needs a (init; update) block"

Try / catch

out=$(yq "$expr" file.yml 2>&1) || { echo "$out"; case "$out" in *"must be given a block"*) echo "append the (init; update) block";; esac; }

Prevention

When it happens

Trigger: Writing `reduce .a[] as $x 0` (no parenthesised body), or `reduce .a[] as $x; . + 1` where a pipe splits off what should be the block, or any typo that prevents the `(init; update)` block from parsing as the RHS.

Common situations: Missing parentheses around the init/update pair; accidentally inserting a `|` between the variable and the block; hand-converted jq one-liners where the semicolon body got separated.

Related errors


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