Tencent/WeKnora · error

failed to normalize SQL: %v

Error message

failed to normalize SQL: %v

What it means

After a successful pg_query.Parse, ValidateAndSecureSQL calls pg_query.Deparse to regenerate normalized SQL text from the parse tree before injecting security conditions. If Deparse fails (a protobuf-to-SQL serialization failure), this error is returned. This is rare and usually indicates a parse-tree feature the deparser cannot render.

Source

Thrown at internal/utils/inject.go:886

		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.
	securedSQL = validator.injectChunkEnabledFilter(securedSQL, tablesInQuery)
	// Inject search scope filter (restrict to allowed KBs and knowledges)
	securedSQL = validator.injectSearchScopeConditions(securedSQL, tablesInQuery)

	return securedSQL, validationResult, nil
}

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Upgrade github.com/pgquery/pgquery-go to the latest version
  2. Simplify or rewrite the query using widely supported PostgreSQL syntax
  3. Check the pg_query-go issue tracker for known Deparse limitations
  4. Restructure the query so the deparser can render it

Example fix

// before (unrenderable syntax)
q := "SELECT * FROM t LIMIT ALL OFFSET NULL"
// after
q := "SELECT * FROM t OFFSET 0"
Defensive patterns

Strategy: fallback

Try / catch

secured, _, err := utils.ValidateAndSecureSQL(sql)
if err != nil && strings.Contains(err.Error(), "failed to normalize SQL") {
    // fail closed: never fall back to unsecured SQL for tenant isolation
    return nil, fmt.Errorf("cannot secure query: %w", err)
}

Prevention

When it happens

Trigger: pg_query.Deparse failing on a successfully parsed statement — typically exotic or very new PostgreSQL syntax the embedded deparser cannot render back to text, or library version bugs.

Common situations: Using a pg_query-go version whose deparser lags the parser; queries with newer PostgreSQL grammar that parse but cannot be deparsed.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/7e5c45bac81bda1d. Report an issue: GitHub.