{"record":{"id":"1ab32c66d89ca331","repo":"risingwavelabs/risingwave","slug":"primary-key-cannot-be-null","errorCode":null,"errorMessage":"primary key {} cannot be null","messagePattern":"primary key (.+?) cannot be null","errorType":"validation","errorClass":"ConnectorError","httpStatus":null,"severity":"error","filePath":"src/connector/src/source/cdc/external/mysql.rs","lineNumber":763,"sourceCode":"                            DataType::Float64 => Value::from(value.into_float64().into_inner()),\n                            DataType::Varchar => Value::from(String::from(value.into_utf8())),\n                            DataType::Date => Value::from(value.into_date().0),\n                            DataType::Time => Value::from(value.into_time().0),\n                            DataType::Timestamp => Value::from(value.into_timestamp().0),\n                            DataType::Decimal => Value::from(value.into_decimal().to_string()),\n                            DataType::Timestamptz => {\n                                // Convert timestamptz to NaiveDateTime for MySQL TIMESTAMP comparison\n                                // MySQL expects NaiveDateTime for TIMESTAMP parameters\n                                let ts = value.into_timestamptz();\n                                let datetime_utc = ts.to_datetime_utc();\n                                let naive_datetime = datetime_utc.naive_utc();\n                                Value::from(naive_datetime)\n                            }\n                            _ => bail!(\"unsupported primary key data type: {}\", ty),\n                        };\n                        ConnectorResult::Ok((pk.to_lowercase(), val))\n                    } else {\n                        bail!(\"primary key {} cannot be null\", pk);\n                    }\n                })\n                .try_collect::<_, _, ConnectorError>()?;\n\n            tracing::debug!(\"snapshot read params: {:?}\", &params);\n            let rs_stream = sql\n                .with(Params::from(params))\n                .stream::<mysql_async::Row, _>(&mut conn)\n                .await?;\n\n            let row_stream = rs_stream.map(|row| {\n                // convert mysql row into OwnedRow\n                let mut row = row?;\n                mysql_row_to_owned_row_with_strict_pk(&mut row, &self.rw_schema, &self.pk_indices)\n                    .map_err(ConnectorError::from)\n            });\n            pin_mut!(row_stream);\n            #[for_await]","sourceCodeStart":745,"sourceCodeEnd":781,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/source/cdc/external/mysql.rs#L745-L781","documentation":"During snapshot pagination the connector reads the last primary-key value of the previous chunk to use as the lower bound of the next query. If that PK value comes back as SQL NULL, it cannot be used to build the range predicate, so the connector bails. A NULL primary key indicates corrupted upstream metadata or an mis-detected key column.","triggerScenarios":"`snapshot_read_inner` (called from `snapshot_read`) reads a chunk where the value of a column serving as the primary key is NULL (`val.is_null()` branch).","commonSituations":"Configuring the CDC table against a table with no real primary key so a nullable column is (wrongly) treated as PK; metadata describing the wrong key column; upstream schema drift making the key column nullable.","solutions":["Ensure the MySQL table has a real PRIMARY KEY (or at minimum a NOT NULL UNIQUE key) before enabling CDC.","Verify the CDC table's configured key columns point to the actual PK columns.","Make the key column NOT NULL upstream (`ALTER TABLE t MODIFY col ... NOT NULL`).","Re-create the CDC table so key metadata is re-derived from the current upstream schema."],"exampleFix":"// before: nullable column treated as key\nCREATE TABLE t (code INT, name VARCHAR(50)); // no PK\n// after\nALTER TABLE t MODIFY code INT NOT NULL;\nALTER TABLE t ADD PRIMARY KEY (code);","handlingStrategy":"validation","validationCode":"// Ensure PK columns are NOT NULL upstream before enabling CDC\nSELECT COLUMN_NAME, IS_NULLABLE FROM INFORMATION_SCHEMA.COLUMNS\n WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? AND COLUMN_KEY = 'PRI';\n-- every row must have IS_NULLABLE = 'NO'","typeGuard":null,"tryCatchPattern":"match snapshot_read(...).await {\n    Err(e) if e.to_string().contains(\"cannot be null\") => {\n        // halt ingestion and require upstream PK fix\n    },\n    r => r?,\n}","preventionTips":["Always define an explicit PRIMARY KEY on MySQL tables used for CDC.","Reject nullable key columns in schema pre-checks.","Watch for ALTERs that drop PK constraints."],"tags":["cdc","mysql","null-value","primary-key"],"backgroundTag":"null-argument","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}