Tencent/WeKnora · error
failed to parse SQL: %v
Error message
failed to parse SQL: %v
What it means
After validation passes, ValidateAndSecureSQL re-parses the SQL with pg_query.Parse to obtain a parse tree for rewriting (tenant/soft-delete filter injection). If the PostgreSQL grammar parser rejects the SQL, this error wraps the parser message. It indicates the SQL string is not valid PostgreSQL syntax.
Source
Thrown at internal/utils/inject.go:880
// Find validator config to check if tenant injection is enabled
validator := &sqlValidator{
tablesWithTenantID: make(map[string]bool),
tablesWithDeletedAt: make(map[string]bool),
}
for _, opt := range opts {
opt(validator)
}
// If no SQL rewriting is enabled, return original SQL
if !validator.enableTenantInjection && !validator.enableSoftDeleteInjection && !validator.enableHiddenKBFilter &&
!validator.enableChunkEnabledFilter && !validator.enableSearchScopeFilter {
return sql, validationResult, nil
}
// Parse again to get normalized SQL
result, err := pg_query.Parse(sql)
if err != nil {
return "", validationResult, fmt.Errorf("failed to parse SQL: %v", err)
}
// Normalize SQL
normalizedSQL, err := pg_query.Deparse(result)
if err != nil {
return "", validationResult, fmt.Errorf("failed to normalize SQL: %v", err)
}
// Build table→alias map from parse tree (respects SQL aliases like "kb", "k")
tablesInQuery := extractTableAliasMap(result)
// Inject tenant conditions
securedSQL := validator.injectTenantConditions(normalizedSQL, tablesInQuery)
// Inject deleted_at IS NULL conditions
securedSQL = validator.injectSoftDeleteConditions(securedSQL, tablesInQuery)
// Inject hidden KB filter (exclude is_temporary = true knowledge bases)
securedSQL = validator.injectHiddenKBFilter(securedSQL, tablesInQuery)
// Exclude disabled chunks from model-visible query results.View on GitHub (pinned to 988cbb0330)
Solutions
- Read the wrapped pg_query error to find the syntax position and fix the SQL
- Verify the query is valid PostgreSQL by running it (or EXPLAIN) against psql
- Check the pg_query library version supports the SQL features used
- Confirm the same string is passed to validation and rewrite (no mutation in between)
Example fix
// before q := "SELECT * FROM knowledge_bases LIMIT ?" secured, _, err := utils.ValidateAndSecureSQL(q) // after q := "SELECT * FROM knowledge_bases LIMIT $1" secured, _, err := utils.ValidateAndSecureSQL(q)
Defensive patterns
Strategy: validation
Validate before calling
// Dry-run with the same parser before calling the library
if _, err := pg_query.Parse(sql); err != nil {
return fmt.Errorf("invalid PostgreSQL syntax: %w", err)
} Try / catch
secured, _, err := utils.ValidateAndSecureSQL(sql)
if err != nil && strings.Contains(err.Error(), "failed to parse SQL") {
return fmt.Errorf("invalid PostgreSQL syntax: %w", err)
} Prevention
- Write PostgreSQL-dialect SQL only (use $1 placeholders, not ?)
- Keep the pg_query-go dependency up to date
- Test generated queries against a real PostgreSQL instance in CI
- Never mutate the SQL string between construction and validation
When it happens
Trigger: SQL that passes the library's lightweight validation but cannot be parsed by the actual PostgreSQL parser via pg_query.Parse — e.g. dialect-specific syntax, malformed expressions, or SQL mutated between validation and this call.
Common situations: Using MySQL/SQLite-flavored syntax that PostgreSQL rejects; pg_query library version mismatch producing different grammar behavior; queries with placeholder/param syntax the parser does not accept.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to normalize SQL: %v
- compound queries (UNION/INTERSECT/EXCEPT) are not allowed
- WITH clause (CTEs) is not allowed
- SELECT INTO is not allowed
- locking clauses (FOR UPDATE, etc.) are not allowed
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/4d01d28b64385c19.
Report an issue: GitHub.