bytebase/bytebase · error
unsupported query node type %T
Error message
unsupported query node type %T
What it means
extractPseudoTableFromQueryNode handles only SELECT, set operations, ResultScanStmt, and ShowStmt nodes; any other AST node reaching it is rejected with errors.Errorf("unsupported query node type %T"). It is a fail-closed guard in the Snowflake query span extractor: the node got classified as base.Select (so it wasn't short-circuited earlier) but the extractor cannot compute result columns for that statement shape. The ShowStmt/ResultScanStmt branches exist specifically for SHOW ... ->> query and related result-pipe statements whose $1 input schema cannot be resolved.
Source
Thrown at backend/plugin/parser/snowflake/query_span_extractor.go:193
return nil, err
}
defer func() {
q.ctes = q.ctes[:originalCTECount]
}()
}
return q.extractPseudoTableFromSetOperation(n)
case *ast.ResultScanStmt:
// FAIL CLOSED: a result-pipe (->>) query reads the previous statement's
// result set, which has no resolvable schema here; resolving the trailing
// SELECT against $1 would produce wrong lineage. Same posture as PIVOT.
return nil, errors.New("result-pipe (->>) statements are not supported for query span extraction yet")
case *ast.ShowStmt:
// Only reachable for SHOW ... ->> <query> (a plain SHOW classifies
// SelectInfoSchema and returns before extraction). Same fail-closed
// posture as ResultScanStmt: $1's schema is not resolvable.
return nil, errors.New("result-pipe (->>) statements are not supported for query span extraction yet")
default:
return nil, errors.Errorf("unsupported query node type %T", node)
}
}
// leftmostSelect descends a set-operation chain's left spine to the SelectStmt
// that textually leads the statement (where omni attaches a leading WITH).
func leftmostSelect(node ast.Node) *ast.SelectStmt {
switch n := node.(type) {
case *ast.SelectStmt:
return n
case *ast.SetOperationStmt:
return leftmostSelect(n.Left)
default:
return nil
}
}
// isRecursiveWith reports whether any CTE in the WITH list carries the RECURSIVE
// flag. Snowflake applies RECURSIVE to the whole WITH list, so a singleView on GitHub (pinned to 1870550677)
Solutions
- Restrict GetQuerySpan input to plain SELECT statements or set operations (UNION/INTERSECT/EXCEPT) — the only fully supported shapes.
- Identify the concrete node type from the %T value in the message and check whether that construct is intentionally unsupported (e.g. result-pipe ->>); rewrite the query without it.
- Handle USE/SET and non-SELECT statements before calling the extractor; non-Select query types already return early and should not reach extraction.
- If the node type is a legitimate SELECT-like statement, file/patch the extractor to add a case for it in extractPseudoTableFromQueryNode.
- Pin the parser/omni version consistently with the extractor version to avoid new unhandled AST node types.
Example fix
// before span, err := extractor.GetQuerySpan(ctx, "SHOW TABLES IN SCHEMA s ->> $1") // after: run the result-pipe query outside lineage, extract span for the plain SELECT span, err := extractor.GetQuerySpan(ctx, "SELECT id, name FROM s.tbl")
Defensive patterns
Strategy: validation
Validate before calling
// Go: pre-screen statements the extractor cannot model
func supportedForSpan(stmt string) bool {
s := strings.ToUpper(strings.TrimSpace(stmt))
return strings.HasPrefix(s, "SELECT") || strings.HasPrefix(s, "WITH") ||
strings.Contains(s, "UNION") || strings.Contains(s, "INTERSECT") || strings.Contains(s, "EXCEPT")
} Try / catch
span, err := extractor.GetQuerySpan(ctx, stmt)
if err != nil {
if strings.HasPrefix(err.Error(), "unsupported query node type") ||
strings.Contains(err.Error(), "result-pipe (->>) statements are not supported") {
log.Printf("statement shape unsupported for lineage: %v", err)
return nil // skip lineage for this statement
}
return err
} Prevention
- Only send SELECT/WITH/set-operation statements to GetQuerySpan.
- Rewrite or exclude SHOW ... ->> $1 result-pipe queries; their input schema is unresolvable.
- Classify statements with getQueryType upstream and skip non-query types before extraction.
- After parser upgrades, re-run lineage tests to catch newly introduced unhandled AST node types.
When it happens
Trigger: Calling GetQuerySpan with a Snowflake statement that the classifier marks as a query but extractPseudoTableFromQueryNode has no case for — i.e. any node type other than *ast.SelectStmt, *ast.SetOperationStmt, *ast.ResultScanStmt, or *ast.ShowStmt (e.g. unusual command forms, PIVOT/other constructs depending on parser version, or a node type newly emitted by a parser upgrade).
Common situations: Feeding non-SELECT commands (CALL, INSERT ... SELECT edge shapes, EXPLAIN variants) that the type classifier still labels Select; parser version drift after an upgrade introduces a new statement type not yet handled; BUG-containing queries mixing constructs the extractor doesn't model; SHOW ... ->> (...) result-pipe queries hitting the fail-closed branch.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- expected exactly 1 statement, got %d
- statement yielded no parse tree
- result-pipe (->>) statements are not supported for query spa
- failed to parse function definition
- failed to extract sensitive fields of the CTE %q
AI-assisted analysis of bytebase/bytebase@1870550677 (2026-09-06).
Data as JSON: /api/errors/b1cb65aa80e529cd.
Report an issue: GitHub.