{"record":{"id":"6fead95d63757440","repo":"risingwavelabs/risingwave","slug":"mysql-table-doesn-t-define-the-primary-key","errorCode":null,"errorMessage":"MySQL table doesn't define the primary key","messagePattern":"MySQL table doesn't define the primary key","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/connector/src/source/cdc/external/mysql.rs","lineNumber":193,"sourceCode":"                        );\n                        None\n                    });\n\n                ColumnDesc::named_with_default_value(\n                    col_name.clone(),\n                    ColumnId::placeholder(),\n                    data_type.clone(),\n                    snapshot_value,\n                )\n            } else {\n                ColumnDesc::named(col_name.clone(), ColumnId::placeholder(), data_type)\n            };\n\n            column_descs.push(column_desc);\n        }\n\n        let pk_names = primary_key_names(&indexes)\n            .ok_or_else(|| anyhow!(\"MySQL table doesn't define the primary key\"))?;\n        Ok(Self {\n            column_descs,\n            pk_names,\n        })\n    }\n\n    pub fn column_descs(&self) -> &Vec<ColumnDesc> {\n        &self.column_descs\n    }\n\n    pub fn pk_names(&self) -> &Vec<String> {\n        &self.pk_names\n    }\n}\n\nfn primary_key_names(indexes: &[IndexInfo]) -> Option<Vec<String>> {\n    indexes\n        .iter()","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/source/cdc/external/mysql.rs#L175-L211","documentation":"When discovering the schema of a CDC source table, RisingWave requires a primary key to construct its internal column descriptors (pk_names). MySQL tables without a PRIMARY KEY (or usable unique index) cannot be tracked for CDC, so connect() aborts schema discovery with this error.","triggerScenarios":"CREATE TABLE ... WITH (connector='mysql-cdc') referencing a MySQL table that has no PRIMARY KEY defined.","commonSituations":"Legacy tables created without keys; views or tables relying on unique secondary indexes only; developer assumed a unique index is enough.","solutions":["Add a PRIMARY KEY to the MySQL source table (ALTER TABLE ... ADD PRIMARY KEY (...)).","Create the RisingWave table on a different table that has a primary key.","If no key can be added, CDC replication of that table is unsupported; pick another ingestion method."],"exampleFix":"// before\nCREATE TABLE orders (...); -- no PK in MySQL\n// after\nALTER TABLE orders ADD PRIMARY KEY (id);","handlingStrategy":"validation","validationCode":"-- run on MySQL before creating the CDC table\nSELECT TABLE_NAME FROM information_schema.TABLES t\nWHERE t.TABLE_SCHEMA = 'mydb' AND t.TABLE_NAME = 'orders'\nAND EXISTS (SELECT 1 FROM information_schema.TABLE_CONSTRAINTS c\n  WHERE c.TABLE_SCHEMA = t.TABLE_SCHEMA AND c.TABLE_NAME = t.TABLE_NAME\n  AND c.CONSTRAINT_TYPE = 'PRIMARY KEY');","typeGuard":"async function tableHasPrimaryKey(conn, schema, table) {\n  const rows = await conn.query(\n    \"SELECT 1 FROM information_schema.TABLE_CONSTRAINTS WHERE TABLE_SCHEMA=? AND TABLE_NAME=? AND CONSTRAINT_TYPE='PRIMARY KEY'\", [schema, table]);\n  return rows.length > 0;\n}","tryCatchPattern":"try { await createCdcTable('orders'); } catch (e) { if (String(e).includes(\"doesn't define the primary key\")) { await mysqlExec('ALTER TABLE orders ADD PRIMARY KEY (id)'); } else throw e; }","preventionTips":["Ensure every MySQL table targeted by CDC has an explicit PRIMARY KEY","Check information_schema.TABLE_CONSTRAINTS before onboarding tables","Do not rely on unique secondary indexes as a substitute for a PK"],"tags":["cdc","mysql","schema","primary-key"],"backgroundTag":"missing-required-config-field","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"}