{"record":{"id":"bb7a0b4c8b03014f","repo":"mikefarah/yq","slug":"reduce-must-be-given-a-block-got-v-instead","errorCode":null,"errorMessage":"reduce must be given a block, got %v instead","messagePattern":"reduce must be given a block, got (.+?) instead","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/yqlib/operator_reduce.go","lineNumber":21,"sourceCode":"import (\n\t\"container/list\"\n\t\"fmt\"\n)\n\nfunc reduceOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {\n\tlog.Debugf(\"reduceOp\")\n\t//.a as $var reduce (0; . + $var)\n\t//lhs is the assignment operator\n\t//rhs is the reduce block\n\t// '.' refers to the current accumulator, initialised to 0\n\t// $var references a single element from the .a\n\n\t//ensure lhs is actually an assignment\n\t//and rhs is a block (empty)\n\tif expressionNode.LHS.Operation.OperationType != assignVariableOpType {\n\t\treturn Context{}, fmt.Errorf(\"reduce must be given a variables assignment, got %v instead\", expressionNode.LHS.Operation.OperationType.Type)\n\t} else if expressionNode.RHS.Operation.OperationType != blockOpType {\n\t\treturn Context{}, fmt.Errorf(\"reduce must be given a block, got %v instead\", expressionNode.RHS.Operation.OperationType.Type)\n\t}\n\n\tarrayExpNode := expressionNode.LHS.LHS\n\tarray, err := d.GetMatchingNodes(context, arrayExpNode)\n\n\tif err != nil {\n\t\treturn Context{}, err\n\t}\n\n\tvariableName := expressionNode.LHS.RHS.Operation.StringValue\n\n\tinitExp := expressionNode.RHS.LHS\n\n\taccum, err := d.GetMatchingNodes(context, initExp)\n\tif err != nil {\n\t\treturn Context{}, err\n\t}\n","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/mikefarah/yq/blob/8b5af0694bb82b41d4ae180fac9972029066f90a/pkg/yqlib/operator_reduce.go#L3-L39","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Supply the parenthesised block: `reduce .a[] as $x (0; . + $x)`.","Make sure there is no pipe operator between `as $x` and the `(init; update)` block.","Include both initialiser and update separated by `;` inside the parentheses.","If you only need a sum/aggregation, verify reduce is the right operator versus `add` or `sum`."],"exampleFix":"// before\nyq 'reduce .a[] as $x 0' file.yml\n// after\nyq 'reduce .a[] as $x (0; . + $x)' file.yml","handlingStrategy":"try-catch","validationCode":"echo \"$expr\" | grep -Eq 'as \\\\$[a-zA-Z_]+ \\\\([^)]*;[^)]*\\\\)' || echo \"reduce needs a (init; update) block\"","typeGuard":null,"tryCatchPattern":"out=$(yq \"$expr\" file.yml 2>&1) || { echo \"$out\"; case \"$out\" in *\"must be given a block\"*) echo \"append the (init; update) block\";; esac; }","preventionTips":["Always include the parenthesised (init; update) body after the variable.","Do not insert a pipe between 'as $var' and the block.","Keep both initialiser and update inside the parentheses separated by ';'.","For simple aggregations, prefer add/sum over reduce."],"tags":["yq","reduce","syntax-error","missing-block"],"backgroundTag":"reduce-invalid-expression-shape","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"}