mikefarah/yq · error
bad expression, got close brackets without matching opening
Error message
bad expression, got close brackets without matching opening bracket
What it means
Same shunting-yard compilation as the collect-bracket case, but for parentheses: a `)` token was reached while the operator stack contained no matching `(`. yq cannot compile the expression to postfix, so it rejects it as a bad expression.
Source
Thrown at pkg/yqlib/expression_postfix.go:107
//traverseArrayCollect is a sneaky op that needs to be included too
//when closing a ]
if len(opStack) > 0 && opStack[len(opStack)-1].Operation != nil && opStack[len(opStack)-1].Operation.OperationType == traverseArrayOpType {
opStack[len(opStack)-1].Operation.Preferences = prefs
opStack, result = popOpToResult(opStack, result)
}
case closeBracket:
for len(opStack) > 0 && opStack[len(opStack)-1].TokenType != openBracket {
missingClosingTokenErr := validateNoOpenTokens(opStack[len(opStack)-1])
if missingClosingTokenErr != nil {
return nil, missingClosingTokenErr
}
opStack, result = popOpToResult(opStack, result)
}
if len(opStack) == 0 {
return nil, errors.New("bad expression, got close brackets without matching opening bracket")
}
// now we should have ( as the last element on the opStack, get rid of it
opStack = opStack[0 : len(opStack)-1]
default:
var currentPrecedence = currentToken.Operation.OperationType.Precedence
// pop off higher precedent operators onto the result
for len(opStack) > 0 &&
opStack[len(opStack)-1].TokenType == operationToken &&
opStack[len(opStack)-1].Operation.OperationType.Precedence > currentPrecedence {
opStack, result = popOpToResult(opStack, result)
}
// add this operator to the opStack
opStack = append(opStack, currentToken)
log.Debugf("put %v onto the opstack", currentToken.toString(true))
}
}
View on GitHub (pinned to 8b5af0694b)
Solutions
- Balance the parentheses in the expression so each `)` has a matching `(`.
- Count parens in generated/templated expressions before running them.
- Check the exact expression passed to yq (echo it or use --expression) to spot quoting or interpolation that removed a `(`.
Example fix
// before yq 'select(.kind == "Deployment"))' file.yaml // after yq 'select(.kind == "Deployment")' file.yaml
Defensive patterns
Strategy: validation
Validate before calling
func parensBalanced(expr string) bool {
var depth int
for _, r := range expr {
if r == '(' {
depth++
} else if r == ')' {
depth--
if depth < 0 {
return false
}
}
}
return depth == 0
} Prevention
- Count parentheses in generated expressions before running yq.
- Keep expressions in single quotes in shell to avoid unintended splitting.
- Test complex expressions with a sample document before using them in production scripts.
When it happens
Trigger: Evaluating a yq expression with a stray `)`, e.g. `yq '.a)'`, `yq 'select(.x == 1))'`, or interpolation/templating that dropped the opening `(` of a function call like `select(`.
Common situations: Half-edited expressions with unmatched parens; string templates where an opening paren is missing; nested selects like `select(.a and (.b))` typo'd as `select(.a and .b))`.
Related errors
- bad path expression, got close collect brackets without matc
- '%v' expects 1 arg but received none
- '%v' expects 2 args but there is %v
- bad expression, please check expression syntax
- must provide a date time format string and an expression, e.
AI-assisted analysis of mikefarah/yq@8b5af0694b (2026-09-05).
Data as JSON: /api/errors/e0c57ec450eeb464.
Report an issue: GitHub.