googleapis/mcp-toolbox · error
unclosed subquery parenthesis
Error message
unclosed subquery parenthesis
What it means
parseSQL tracks subquery parentheses while scanning the statement. If the scan ends while still inside a subquery (inSubquery is true), the SQL is malformed — a '(' opened a subquery that was never closed — so parsing cannot complete and the parser returns this error.
Source
Thrown at internal/tools/bigquery/bigquerycommon/table_name_parser.go:394
case stateInRawTripleSingleQuoteString:
if strings.HasPrefix(remaining, "'''") {
state = stateNormal
i += 3
} else {
i++
}
case stateInRawTripleDoubleQuoteString:
if strings.HasPrefix(remaining, `"""`) {
state = stateNormal
i += 3
} else {
i++
}
}
}
if inSubquery {
return 0, fmt.Errorf("unclosed subquery parenthesis")
}
return len(sql), nil
}
// parseIdentifierSequence parses a sequence of dot-separated identifiers.
// It returns the parts of the identifier, the number of characters consumed, and an error.
func parseIdentifierSequence(s string) ([]string, int, error) {
var parts []string
var totalConsumed int
for {
remaining := s[totalConsumed:]
trimmed := strings.TrimLeftFunc(remaining, unicode.IsSpace)
totalConsumed += len(remaining) - len(trimmed)
current := s[totalConsumed:]
if len(current) == 0 {
breakView on GitHub (pinned to 8cc6e09de2)
Solutions
- Count and balance all parentheses in the query; add the missing ')'
- Print/format the SQL before parsing to spot the unbalanced section
- If the SQL is built dynamically, fix the template so subqueries are always fully closed
- Validate the SQL in the BigQuery console / dry run to locate the syntax error
Example fix
// before SELECT * FROM proj.ds.t WHERE id IN (SELECT id FROM proj.ds.other; // after SELECT * FROM proj.ds.t WHERE id IN (SELECT id FROM proj.ds.other);
Defensive patterns
Strategy: validation
Validate before calling
func balancedParens(sql string) bool {
depth := 0
inStr, inBacktick := false, false
for _, r := range sql {
switch {
case r == '`': inBacktick = !inBacktick
case r == '\'' && !inBacktick: inStr = !inStr
case !inStr && !inBacktick && r == '(': depth++
case !inStr && !inBacktick && r == ')': depth--
}
if depth < 0 { return false }
}
return depth == 0
} Try / catch
if !balancedParens(sql) {
return fmt.Errorf("query has unbalanced parentheses; check subqueries")
}
_, err := parser.Parse(sql)
if err != nil {
return fmt.Errorf("parse failed: %w", err)
} Prevention
- Use an SQL formatter/linter to check paren balance before submitting
- Avoid hand-building SQL via string concatenation; use parameterized builders
- Test templated queries with representative inputs
When it happens
Trigger: Calling parseSQL/TableParser on SQL with an unmatched '(' inside the query, e.g. a truncated query or a missing closing parenthesis after a subquery or IN (...) list.
Common situations: Hand-written or templated SQL with mismatched parens; string concatenation that drops the tail of a query; copy-paste truncation; code generators producing broken subqueries.
Related errors
- EXECUTE IMMEDIATE is not allowed when dataset restrictions a
- unanalyzable statements like '%s %s' are not allowed
- dataset-level operations like '%s %s' are not allowed when d
- unclosed backtick identifier
- query contains table '%s' without project ID, and no default
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/f07c87f133e2b190.
Report an issue: GitHub.