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

  1. Read the wrapped pg_query error to find the syntax position and fix the SQL
  2. Verify the query is valid PostgreSQL by running it (or EXPLAIN) against psql
  3. Check the pg_query library version supports the SQL features used
  4. 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

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

Related errors


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