{"record":{"id":"83454654a0952407","repo":"risingwavelabs/risingwave","slug":"postgresql-table-exists-but-the-connection-use-834546","errorCode":null,"errorMessage":"PostgreSQL table {} exists, but the connection user `{}` does not have {} privilege on it.{} Grant privileges on the upstream PostgreSQL database: {}","messagePattern":"PostgreSQL table (.+?) exists, but the connection user `(.+?)` does not have (.+?) privilege on it\\.(.+?) Grant privileges on the upstream PostgreSQL database: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/connector/src/connector_common/postgres.rs","lineNumber":363,"sourceCode":"\n        if !privilege_status.has_schema_usage {\n            return Err(anyhow!(\n                \"PostgreSQL table {} exists, but the connection user `{}` does not have USAGE privilege on schema `{}`. Grant privileges on the upstream PostgreSQL database: {}\",\n                format_pg_table_name(schema, table),\n                privilege_status.user_name,\n                schema,\n                format_grant_usage(schema, &privilege_status.user_name),\n            )\n            .into());\n        }\n\n        if !privilege_status.has_table_privilege {\n            let column_privilege_msg = if privilege_status.has_any_column_privilege {\n                \" The user has column-level privilege on at least one column, but RisingWave requires table-level privilege for CDC schema discovery and snapshot reads.\"\n            } else {\n                \"\"\n            };\n            return Err(anyhow!(\n                \"PostgreSQL table {} exists, but the connection user `{}` does not have {} privilege on it.{} Grant privileges on the upstream PostgreSQL database: {}\",\n                format_pg_table_name(schema, table),\n                privilege_status.user_name,\n                required_privilege,\n                column_privilege_msg,\n                format_required_table_grants(\n                    schema,\n                    table,\n                    &privilege_status.user_name,\n                    required_privilege\n                ),\n            )\n            .into());\n        }\n\n        Ok(())\n    }\n","sourceCodeStart":345,"sourceCodeEnd":381,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/connector_common/postgres.rs#L345-L381","documentation":"When setting up PostgreSQL CDC, RisingWave checks that the connection user holds table-level privileges (e.g. SELECT) on the source table. This error is thrown by `ensure_table_privilege` when the table exists but the user lacks the required table-level privilege, and it appends a note when the user only has column-level privileges, since CDC schema discovery and snapshot reads need full table access.","triggerScenarios":"Calling the CDC table creation path (`ensure_table_privilege` during connector setup) where a privilege query reports `has_table_privilege == false` for the configured table, schema, and connection user.","commonSituations":"The DBA granted only column-level SELECT on some columns; the user was granted privileges on other tables in the schema but not this one; the role was created after table creation without default privileges; connecting via a limited service account.","solutions":["Run `GRANT SELECT ON <schema>.<table> TO <user>;` as superuser on the upstream PostgreSQL database","Verify current privileges with `SELECT * FROM information_schema.role_table_grants WHERE grantee = '<user>';`","If column-level grants were intended, replace them with table-level grants: `REVOKE SELECT(...) ON ...; GRANT SELECT ON ...;`","Re-run the RisingWave CDC table creation after granting"],"exampleFix":"-- before (column-level only)\nGRANT SELECT (id, payload) ON public.orders TO rw_user;\n-- after\nGRANT SELECT ON public.orders TO rw_user;","handlingStrategy":"validation","validationCode":"-- run as superuser before creating the RW CDC table\nSELECT has_table_privilege('rw_user', 'public.orders', 'SELECT') AS table_ok;\n-- if false, fix with:\nGRANT SELECT ON public.orders TO rw_user;","typeGuard":null,"tryCatchPattern":"match ensure_table_privilege_result {\n    Err(e) if e.to_string().contains(\"does not have\") => {\n        // surface remediation SQL to the DBA before retrying\n        return Err(GuidanceError::new(e, \"GRANT SELECT ON <table> TO <user>;\"));\n    }\n    r => r,\n}","preventionTips":["Grant table-level SELECT (not column-level) to the CDC user","Use ALTER DEFAULT PRIVILEGES so future tables grant automatically","Verify privileges with information_schema.role_table_grants before wiring CDC"],"tags":["postgres","cdc","privilege","permissions"],"backgroundTag":"permission-denied","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}