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 {
			break

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Count and balance all parentheses in the query; add the missing ')'
  2. Print/format the SQL before parsing to spot the unbalanced section
  3. If the SQL is built dynamically, fix the template so subqueries are always fully closed
  4. 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

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


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/f07c87f133e2b190. Report an issue: GitHub.