mikefarah/yq · error
bad expression, could not find matching `]`
Error message
bad expression, could not find matching `]`
What it means
During infix-to-postfix conversion, validateNoOpenTokens detects an unclosed openCollect token ('[') at the end of the token stream. This means a collect/array bracket was opened but never closed, so the expression cannot be evaluated.
Source
Thrown at pkg/yqlib/expression_postfix.go:30
type expressionPostFixerImpl struct {
}
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:View on GitHub (pinned to 8b5af0694b)
Solutions
- Add the matching `]` to close the collect (e.g. `[.a, .b]`)
- Quote the expression properly so the shell doesn't eat brackets (single quotes)
- If using multi-line expressions, verify the final line closes all brackets
Example fix
// before yq '[.a' file.yml // after yq '[.a]' file.yml
Defensive patterns
Strategy: validation
Validate before calling
// naive balance check before invoking yq
depth := 0
for _, r := range expr {
switch r {
case '[': depth++
case ']': depth--
}
if depth < 0 { break }
}
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
- Single-quote expressions so shell does not strip brackets
- Close collects immediately after opening: `[` ... `]` before filling in the middle
- Add a bracket-balance lint step for scripts that build expressions dynamically
When it happens
Trigger: Running `yq '[.a' file.yml` or any expression with `[` without matching `]`, e.g. `yq '.a[.b'` or an incomplete map/collect in a select.
Common situations: Hand-written collect expressions in CI scripts, truncated expressions from shell quoting, forgetting to close a multi-line expression.
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/aa1d0202c6d4e762.
Report an issue: GitHub.