mikefarah/yq · error
bad expression, could not find matching `}`
Error message
bad expression, could not find matching `}`
What it means
validateNoOpenTokens finds an unclosed openCollectObject token ('{') at the end of conversion. An object-collect was opened in the expression but never closed with '}', so the expression is incomplete and rejected.
Source
Thrown at pkg/yqlib/expression_postfix.go:32
}
func newExpressionPostFixer() expressionPostFixer {
return &expressionPostFixerImpl{}
}
func popOpToResult(opStack []*token, result []*Operation) ([]*token, []*Operation) {
var newOp *token
opStack, newOp = opStack[0:len(opStack)-1], opStack[len(opStack)-1]
log.Debugf("popped %v from opstack to results", newOp.toString(true))
return opStack, append(result, newOp.Operation)
}
func validateNoOpenTokens(token *token) error {
switch token.TokenType {
case openCollect:
return fmt.Errorf(("bad expression, could not find matching `]`"))
case openCollectObject:
return fmt.Errorf(("bad expression, could not find matching `}`"))
case openBracket:
return fmt.Errorf(("bad expression, could not find matching `)`"))
}
return nil
}
func (p *expressionPostFixerImpl) ConvertToPostfix(infixTokens []*token) ([]*Operation, error) {
var result []*Operation
// surround the whole thing with brackets
var opStack = []*token{{TokenType: openBracket}}
var tokens = append(infixTokens, &token{TokenType: closeBracket})
for _, currentToken := range tokens {
log.Debugf("postfix processing currentToken %v", currentToken.toString(true))
switch currentToken.TokenType {
case openBracket, openCollect, openCollectObject:
opStack = append(opStack, currentToken)
log.Debugf("put %v onto the opstack", currentToken.toString(true))View on GitHub (pinned to 8b5af0694b)
Solutions
- Add the matching `}` to close the object collect (e.g. `{a: .a}`)
- Single-quote the expression to prevent shell brace expansion from interfering
- Check templates/heredocs that generate the expression for dropped braces
Example fix
// before
yq '{a: .a' file.yml
// after
yq '{a: .a}' file.yml Defensive patterns
Strategy: validation
Validate before calling
depth := strings.Count(expr, "{") - strings.Count(expr, "}")
if depth != 0 {
return fmt.Errorf("unbalanced { } in expression %q", expr)
} Try / catch
out, err := runYq(expr, file)
if err != nil && strings.Contains(err.Error(), "could not find matching `}`") {
return fmt.Errorf("unclosed { in expression %q", expr)
} Prevention
- Beware shell brace expansion: always single-quote yq expressions containing `{}`
- Write object collects in one line first, then extend
- Template-generated expressions: assert braces survive substitution
When it happens
Trigger: Running `yq '{a: .a' file.yml` or expressions like `{"key": .value}` missing the closing brace, often from truncated quoting.
Common situations: Building object-collect expressions dynamically in scripts, shell variable expansion swallowing the `}` (brace expansion!), multi-line edits.
Related errors
- bad expression, could not find matching `]`
- bad expression, could not find matching `)`
- bad expression - probably missing close bracket on %v
- '%v' expects 1 arg but received none
- '%v' expects 2 args but there is %v
AI-assisted analysis of mikefarah/yq@8b5af0694b (2026-09-05).
Data as JSON: /api/errors/62a93d49812e9f69.
Report an issue: GitHub.