Tencent/WeKnora · error
WITH clause (CTEs) is not allowed
Error message
WITH clause (CTEs) is not allowed
What it means
When the validator is configured with checkCTEs enabled, validateSelectStmt rejects any SELECT carrying a WITH clause (stmt.WithClause != nil). Common Table Expressions are disallowed because they can obscure which tables are actually referenced, defeating the validator's table allowlisting. The query is rejected before the FROM clause is inspected.
Source
Thrown at internal/utils/inject.go:1353
if len(sql) > v.maxLength {
return fmt.Errorf("SQL query too long (max %d characters)", v.maxLength)
}
return nil
}
// validateSelectStmt validates a SELECT statement with configured options
func (v *sqlValidator) validateSelectStmt(stmt *pg_query.SelectStmt, result *SQLValidationResult) error {
tablesInQuery := make(map[string]string) // table name -> alias
// Check for UNION/INTERSECT/EXCEPT (compound queries)
if stmt.Op != pg_query.SetOperation_SETOP_NONE {
return fmt.Errorf("compound queries (UNION/INTERSECT/EXCEPT) are not allowed")
}
// Check for WITH clause (CTEs)
if v.checkCTEs && stmt.WithClause != nil {
return fmt.Errorf("WITH clause (CTEs) is not allowed")
}
// Check for INTO clause (SELECT INTO)
if stmt.IntoClause != nil {
return fmt.Errorf("SELECT INTO is not allowed")
}
// Check for LOCKING clause (FOR UPDATE, etc.)
if len(stmt.LockingClause) > 0 {
return fmt.Errorf("locking clauses (FOR UPDATE, etc.) are not allowed")
}
// Validate FROM clause
for _, fromItem := range stmt.FromClause {
if err := v.validateFromItem(fromItem, tablesInQuery, result); err != nil {
return err
}
}View on GitHub (pinned to 988cbb0330)
Solutions
- Inline the CTE as a subquery in FROM: SELECT * FROM (SELECT ...) AS t.
- Duplicate the underlying query logic without WITH.
- Disable the checkCTEs option in the validator if CTEs are safe in your context.
Example fix
// before (rejected when checkCTEs=true) q := "WITH active AS (SELECT id FROM users WHERE active) SELECT * FROM active" // after q := "SELECT * FROM (SELECT id FROM users WHERE active) AS active"
Defensive patterns
Strategy: validation
Validate before calling
re := regexp.MustCompile(`(?i)^\s*WITH[\s(]`)
if re.MatchString(sql) {
return fmt.Errorf("CTE (WITH clause) rejected; inline it as a subquery or disable checkCTEs")
} Prevention
- Prefer subqueries over CTEs in code that goes through this validator.
- Know your validator's checkCTEs setting before writing queries.
- Add a pre-submission lint rule flagging leading WITH.
- When refactoring long queries for readability, re-run validation tests.
When it happens
Trigger: Calling the validation API with a query like "WITH t AS (SELECT ...) SELECT * FROM t" while the validator has checkCTEs = true (whether by explicit option or default).
Common situations: Developers refactor long queries into CTEs for readability and suddenly fail validation; query builders that emit WITH for recursive or reusable subqueries; teams upgrading the library where checkCTEs defaults changed to true.
Related errors
- compound queries (UNION/INTERSECT/EXCEPT) are not allowed
- SELECT INTO is not allowed
- locking clauses (FOR UPDATE, etc.) are not allowed
- invite code has expired
- join request not found
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/d218476276a827c3.
Report an issue: GitHub.