{"record":{"id":"e0c57ec450eeb464","repo":"mikefarah/yq","slug":"bad-expression-got-close-brackets-without-matchin","errorCode":null,"errorMessage":"bad expression, got close brackets without matching opening bracket","messagePattern":"bad expression, got close brackets without matching opening bracket","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/yqlib/expression_postfix.go","lineNumber":107,"sourceCode":"\n\t\t\t//traverseArrayCollect is a sneaky op that needs to be included too\n\t\t\t//when closing a ]\n\t\t\tif len(opStack) > 0 && opStack[len(opStack)-1].Operation != nil && opStack[len(opStack)-1].Operation.OperationType == traverseArrayOpType {\n\t\t\t\topStack[len(opStack)-1].Operation.Preferences = prefs\n\t\t\t\topStack, result = popOpToResult(opStack, result)\n\t\t\t}\n\n\t\tcase closeBracket:\n\t\t\tfor len(opStack) > 0 && opStack[len(opStack)-1].TokenType != openBracket {\n\t\t\t\tmissingClosingTokenErr := validateNoOpenTokens(opStack[len(opStack)-1])\n\t\t\t\tif missingClosingTokenErr != nil {\n\t\t\t\t\treturn nil, missingClosingTokenErr\n\t\t\t\t}\n\n\t\t\t\topStack, result = popOpToResult(opStack, result)\n\t\t\t}\n\t\t\tif len(opStack) == 0 {\n\t\t\t\treturn nil, errors.New(\"bad expression, got close brackets without matching opening bracket\")\n\t\t\t}\n\t\t\t// now we should have ( as the last element on the opStack, get rid of it\n\t\t\topStack = opStack[0 : len(opStack)-1]\n\n\t\tdefault:\n\t\t\tvar currentPrecedence = currentToken.Operation.OperationType.Precedence\n\t\t\t// pop off higher precedent operators onto the result\n\t\t\tfor len(opStack) > 0 &&\n\t\t\t\topStack[len(opStack)-1].TokenType == operationToken &&\n\t\t\t\topStack[len(opStack)-1].Operation.OperationType.Precedence > currentPrecedence {\n\t\t\t\topStack, result = popOpToResult(opStack, result)\n\t\t\t}\n\t\t\t// add this operator to the opStack\n\t\t\topStack = append(opStack, currentToken)\n\t\t\tlog.Debugf(\"put %v onto the opstack\", currentToken.toString(true))\n\t\t}\n\t}\n","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/mikefarah/yq/blob/8b5af0694bb82b41d4ae180fac9972029066f90a/pkg/yqlib/expression_postfix.go#L89-L125","documentation":"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.","triggerScenarios":"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(`.","commonSituations":"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))`.","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 `(`."],"exampleFix":"// before\nyq 'select(.kind == \"Deployment\"))' file.yaml\n// after\nyq 'select(.kind == \"Deployment\")' file.yaml","handlingStrategy":"validation","validationCode":"func parensBalanced(expr string) bool {\n    var depth int\n    for _, r := range expr {\n        if r == '(' {\n            depth++\n        } else if r == ')' {\n            depth--\n            if depth < 0 {\n                return false\n            }\n        }\n    }\n    return depth == 0\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["expression","parser","brackets"],"backgroundTag":"unbalanced-bracket-expression","analyzedSha":"8b5af0694bb82b41d4ae180fac9972029066f90a","analyzedAt":"2026-09-05T10:57:22.766Z","contentChangedAt":"2026-09-05T10:57:22.766Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}