{"record":{"id":"7e5c45bac81bda1d","repo":"Tencent/WeKnora","slug":"failed-to-normalize-sql-v","errorCode":null,"errorMessage":"failed to normalize SQL: %v","messagePattern":"failed to normalize SQL: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/utils/inject.go","lineNumber":886,"sourceCode":"\t\topt(validator)\n\t}\n\n\t// If no SQL rewriting is enabled, return original SQL\n\tif !validator.enableTenantInjection && !validator.enableSoftDeleteInjection && !validator.enableHiddenKBFilter &&\n\t\t!validator.enableChunkEnabledFilter && !validator.enableSearchScopeFilter {\n\t\treturn sql, validationResult, nil\n\t}\n\n\t// Parse again to get normalized SQL\n\tresult, err := pg_query.Parse(sql)\n\tif err != nil {\n\t\treturn \"\", validationResult, fmt.Errorf(\"failed to parse SQL: %v\", err)\n\t}\n\n\t// Normalize SQL\n\tnormalizedSQL, err := pg_query.Deparse(result)\n\tif err != nil {\n\t\treturn \"\", validationResult, fmt.Errorf(\"failed to normalize SQL: %v\", err)\n\t}\n\n\t// Build table→alias map from parse tree (respects SQL aliases like \"kb\", \"k\")\n\ttablesInQuery := extractTableAliasMap(result)\n\n\t// Inject tenant conditions\n\tsecuredSQL := validator.injectTenantConditions(normalizedSQL, tablesInQuery)\n\t// Inject deleted_at IS NULL conditions\n\tsecuredSQL = validator.injectSoftDeleteConditions(securedSQL, tablesInQuery)\n\t// Inject hidden KB filter (exclude is_temporary = true knowledge bases)\n\tsecuredSQL = validator.injectHiddenKBFilter(securedSQL, tablesInQuery)\n\t// Exclude disabled chunks from model-visible query results.\n\tsecuredSQL = validator.injectChunkEnabledFilter(securedSQL, tablesInQuery)\n\t// Inject search scope filter (restrict to allowed KBs and knowledges)\n\tsecuredSQL = validator.injectSearchScopeConditions(securedSQL, tablesInQuery)\n\n\treturn securedSQL, validationResult, nil\n}","sourceCodeStart":868,"sourceCodeEnd":904,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/utils/inject.go#L868-L904","documentation":"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.","triggerScenarios":"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.","commonSituations":"Using a pg_query-go version whose deparser lags the parser; queries with newer PostgreSQL grammar that parse but cannot be deparsed.","solutions":["Upgrade github.com/pgquery/pgquery-go to the latest version","Simplify or rewrite the query using widely supported PostgreSQL syntax","Check the pg_query-go issue tracker for known Deparse limitations","Restructure the query so the deparser can render it"],"exampleFix":"// before (unrenderable syntax)\nq := \"SELECT * FROM t LIMIT ALL OFFSET NULL\"\n// after\nq := \"SELECT * FROM t OFFSET 0\"","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"secured, _, err := utils.ValidateAndSecureSQL(sql)\nif err != nil && strings.Contains(err.Error(), \"failed to normalize SQL\") {\n    // fail closed: never fall back to unsecured SQL for tenant isolation\n    return nil, fmt.Errorf(\"cannot secure query: %w\", err)\n}","preventionTips":["Keep github.com/pgquery/pgquery-go at the latest release so parser and deparser versions match","Avoid exotic/newest PostgreSQL syntax in queries meant for rewriting","Add a CI test that deparses every query template used in production","On deparse failure, fail closed rather than executing unsecured SQL"],"tags":["sql","postgres","deparse"],"backgroundTag":"sql-deparse-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}