mikefarah/yq · error
must use variable with a pipe, e.g. `exp as $x | ...`
Error message
must use variable with a pipe, e.g. `exp as $x | ...`
What it means
The `as` variable-binding operator only makes sense inside a pipeline (`exp as $x | ...`). yq parses variables so that, when used outside a pipe context, the placeholder handler `useWithPipe` runs and returns this error instead of silently doing nothing.
Source
Thrown at pkg/yqlib/operator_variables.go:23
"fmt"
)
func getVariableOperator(_ *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
variableName := expressionNode.Operation.StringValue
log.Debugf("getVariableOperator %v", variableName)
result := context.GetVariable(variableName)
if result == nil {
result = list.New()
}
return context.ChildContext(result), nil
}
type assignVarPreferences struct {
IsReference bool
}
func useWithPipe(_ *dataTreeNavigator, _ Context, _ *ExpressionNode) (Context, error) {
return Context{}, fmt.Errorf("must use variable with a pipe, e.g. `exp as $x | ...`")
}
// variables are like loops in jq
// https://stedolan.github.io/jq/manual/#Variable
func variableLoop(d *dataTreeNavigator, context Context, originalExp *ExpressionNode) (Context, error) {
log.Debug("variable loop!")
results := list.New()
var evaluateAllTogether = true
for matchEl := context.MatchingNodes.Front(); matchEl != nil; matchEl = matchEl.Next() {
evaluateAllTogether = evaluateAllTogether && matchEl.Value.(*CandidateNode).EvaluateTogether
if !evaluateAllTogether {
break
}
}
if evaluateAllTogether {
return variableLoopSingleChild(d, context, originalExp)
}
View on GitHub (pinned to 8b5af0694b)
Solutions
- Add the pipe and continuation, e.g. `.a as $x | .b + $x`
- If you only wanted to reference a value, drop the `as` syntax and pipe the expression directly
- Check the expression string for truncation — the `| ...` half may have been lost when quoting in the shell
- Consult the variables docs: bindings are per-expression, not persistent across yq runs
Example fix
// before yq '.a as $x' file.yaml // after yq '.a as $x | .b + $x' file.yaml
Defensive patterns
Strategy: try-catch
Validate before calling
// Validate expression has a pipe continuation after 'as'
if strings.Contains(expr, " as $") && !strings.Contains(expr, "|") {
return fmt.Errorf("'as' requires a pipe continuation: exp as $x | ...")
} Try / catch
out, err := yqEval(expr, doc)
if err != nil && strings.Contains(err.Error(), "must use variable with a pipe") {
// fix expression: append '| ...' continuation
} Prevention
- Always follow `as $x` with `|` and a consuming expression
- Test expressions in the shell with single quotes to avoid mangling
- Refer to yq variable docs when porting jq snippets
When it happens
Trigger: Using a variable operator form that is not attached to a pipe, e.g. `yq '$x'` with no binding, or an expression where `as` isn't followed by `|`, causing the lexer to dispatch to useWithPipe.
Common situations: Copy-pasting jq snippets without the trailing pipe, forgetting the `| ...` continuation after `as $x`, or writing `yq 'exp as $x'` and expecting the binding to persist to a later invocation.
Related errors
- RHS of 'as' operator must be a variable name e.g. $foo
- with must be given a block (;), got %v instead
- yaml node has no content
- orderedMap: invalid yaml node
- INI encoder supports only MappingNode at the root level, got
AI-assisted analysis of mikefarah/yq@8b5af0694b (2026-09-05).
Data as JSON: /api/errors/94b94df5a987d556.
Report an issue: GitHub.