risingwavelabs/risingwave · error · ConnectorError
failed to parse mysql timestamp value
Error message
failed to parse mysql timestamp value
What it means
timestamp_val_to_timestamptz parses a MySQL timestamp literal in the fixed format '%Y-%m-%d %H:%M:%S' and converts it to a UTC timestamptz string. If the text does not match this exact format, chrono's NaiveDateTime::parse_from_str fails and the error (with the chrono error as context) is returned.
Source
Thrown at src/connector/src/source/cdc/external/mysql.rs:264
// interpret its value
if data_type == &DataType::Timestamptz {
val = timestamp_val_to_timestamptz(val.as_str())?;
}
Some(ScalarImpl::from_text(val.as_str(), data_type).map_err(|e| anyhow!(e)).context(
"failed to parse mysql default value expression, only constant is supported",
)?)
}
ColumnDefault::CurrentTimestamp | ColumnDefault::CustomExpr(_) => {
bail!("MySQL CURRENT_TIMESTAMP and custom expression default value not supported")
}
};
Ok(datum)
}
pub fn timestamp_val_to_timestamptz(value_text: &str) -> ConnectorResult<String> {
let format = "%Y-%m-%d %H:%M:%S";
let naive_datetime = NaiveDateTime::parse_from_str(value_text, format)
.map_err(|err| anyhow!("failed to parse mysql timestamp value").context(err))?;
let postgres_timestamptz: DateTime<chrono::Utc> =
DateTime::<chrono::Utc>::from_naive_utc_and_offset(naive_datetime, chrono::Utc);
Ok(postgres_timestamptz
.format("%Y-%m-%d %H:%M:%S%:z")
.to_string())
}
pub fn type_name_to_mysql_type(ty_name: &str) -> Option<ColumnType> {
// Debezium schema change message may include extra qualifiers, e.g. `BIGINT UNSIGNED`,
// `BIGINT(20) UNSIGNED`, `INT UNSIGNED ZEROFILL`, etc.
let ty = ty_name.trim().to_lowercase();
let tokens = ty
.split(|c: char| c.is_whitespace() || matches!(c, '(' | ')' | ','))
.filter(|token| !token.is_empty())
.collect_vec();
let base = tokens.first().copied().unwrap_or_default();
let second = tokens.get(1).copied();
let is_unsigned = tokens.contains(&"unsigned");View on GitHub (pinned to 6469eb736d)
Solutions
- Normalize the MySQL default to 'YYYY-MM-DD HH:MM:SS' format (no fractional seconds, no 'T').
- Replace the default with a constant literal in the accepted format.
- Patch timestamp_val_to_timestamptz to accept fractional seconds (e.g. try multiple chrono formats) if you control the connector code.
Example fix
// before (MySQL) ALTER TABLE t MODIFY ts TIMESTAMP(3) DEFAULT '2024-01-01 00:00:00.000'; // after ALTER TABLE t MODIFY ts TIMESTAMP DEFAULT '2024-01-01 00:00:00';
Defensive patterns
Strategy: validation
Validate before calling
function isMysqlTimestampLiteral(v) {
return /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/.test(String(v));
} Type guard
function canParseAsNaiveDateTime(v) {
return /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/.test(v) && !isNaN(Date.parse(v.replace(" ", "T") + "Z"));
} Try / catch
try { await createCdcTable('t'); } catch (e) { if (String(e).includes('failed to parse mysql timestamp value')) { /* reformat the default to 'YYYY-MM-DD HH:MM:SS' in MySQL and retry */ } else throw e; } Prevention
- Format timestamp defaults as 'YYYY-MM-DD HH:MM:SS' with no fractional seconds or 'T'
- Avoid TIMESTAMP(n) defaults that resolve to fractional-second literals
- Never use zero-dates like '0000-00-00 00:00:00' as defaults
When it happens
Trigger: A MySQL TIMESTAMP/DATETIME column default whose string value includes fractional seconds ('2024-01-01 00:00:00.123'), timezone offsets, or another formatting variant; also reached via parse_schema_change handling default values.
Common situations: MySQL defaults like CURRENT_TIMESTAMP(3) resolved to values with microseconds; locale or zero-date values ('0000-00-00 00:00:00'); defaults written with 'T' separators.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to parse mysql default value expression, only constan
- received a DDL message, please set `canal.instance.filter.qu
- no value found at column: {}, index: {}
- failed to deserialize MySQL value into rust value
- failed to deserialize MySQL value into rw value
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/b3cb9f340cb19f34.
Report an issue: GitHub.