mikefarah/yq · error
bad path expression, got close collect brackets without matc
Error message
bad path expression, got close collect brackets without matching opening bracket
What it means
yq compiles expressions to postfix (RPN) using a shunting-yard algorithm that tracks open/close bracket pairs. A `]` (close collect bracket) arrived while the operator stack had no matching `[`, so the expression is structurally unbalanced. The library throws this rather than guessing intent.
Source
Thrown at pkg/yqlib/expression_postfix.go:67
opStack = append(opStack, currentToken)
log.Debugf("put %v onto the opstack", currentToken.toString(true))
case closeCollect, closeCollectObject:
var opener tokenType = openCollect
var collectOperator = collectOpType
if currentToken.TokenType == closeCollectObject {
opener = openCollectObject
collectOperator = collectObjectOpType
}
for len(opStack) > 0 && opStack[len(opStack)-1].TokenType != opener {
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 path expression, got close collect 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]
log.Debugf("deleting open bracket from opstack")
//and append a collect to the result
// hack - see if there's the optional traverse flag
// on the close op - move it to the traverse array op
// allows for .["cat"]?
prefs := traversePreferences{}
closeTokenMatch := currentToken.Match
if closeTokenMatch[len(closeTokenMatch)-1:] == "?" {
prefs.OptionalTraverse = true
}
result = append(result, &Operation{OperationType: collectOperator})
log.Debugf("put collect onto the result")
if opener != openCollect {View on GitHub (pinned to 8b5af0694b)
Solutions
- Fix the expression so every `]` has a matching `[` (e.g. `.items[]` not `.items]`).
- Quote the expression in single quotes so the shell does not mangle brackets: yq '.a[0]'.
- If generating expressions dynamically, validate bracket balance before invoking yq.
Example fix
// before (unbalanced) yq '.items]' file.yaml // after yq '.items[]' file.yaml
Defensive patterns
Strategy: validation
Validate before calling
func balanced(expr string) bool {
var depth int
for _, r := range expr {
switch r {
case '[':
depth++
case ']':
depth--
if depth < 0 {
return false
}
}
}
return depth == 0
} Prevention
- Single-quote yq expressions in shell so brackets aren't glob-expanded or stripped.
- When templating expressions, assert bracket balance before invoking yq.
- Prefer --expression '<expr>' to positional args in scripts for predictable parsing.
When it happens
Trigger: Evaluating any yq expression containing `]` without a preceding `[`, e.g. `yq '.foo]'`, `yq 'select(.a)]'`, or a programmatically built expression string that lost its opening `[` (often via shell quoting stripping brackets or string interpolation).
Common situations: Shell quoting issues where `[` is treated as a glob/stripped by the shell; templating a yq expression from variables where the array-collect part is conditionally omitted; typos like `.items]` instead of `.items[]`.
Related errors
- bad expression, got close brackets without matching opening
- '%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/13497b784f3f7d13.
Report an issue: GitHub.