risingwavelabs/risingwave · error · ConnectorError
scan.startup.timestamp.millis is required
Error message
scan.startup.timestamp.millis is required
What it means
The Kinesis source connector's `new` parses `scan.startup.mode`; when it is set to `"timestamp"`, the property `scan.startup.timestamp.millis` (mapped to `properties.start_timestamp_millis`) must also be provided. If it is absent, `bail!` aborts source construction with this message. It enforces that a timestamp startup mode always carries an actual epoch-milliseconds value to seek from.
Solutions
- Add `scan.startup.timestamp.millis = '<epoch_ms>'` to the source WITH clause.
- If you actually want to start from the oldest data, set `scan.startup.mode = 'earliest'` instead.
- Validate the pair of options in the CREATE SOURCE SQL before running it.
Example fix
// before WITH ( connector = 'kinesis', stream_name = 'events', scan.startup.mode = 'timestamp' ) // after WITH ( connector = 'kinesis', stream_name = 'events', scan.startup.mode = 'timestamp', scan.startup.timestamp.millis = '1700000000000' )
Defensive patterns
Strategy: validation
Validate before calling
// Before creating/updating the source, validate the option pair
let mode = props.get("scan.startup.mode").map(|s| s.as_str());
if mode == Some("timestamp") {
props.get("scan.startup.timestamp.millis")
.and_then(|v| v.parse::<i64>().ok())
.ok_or_else(|| anyhow!("scan.startup.mode='timestamp' requires scan.startup.timestamp.millis (epoch ms)"))?;
} Prevention
- Always set scan.startup.timestamp.millis together with scan.startup.mode='timestamp' in DDL templates.
- Add a pre-deployment config lint that checks required companion fields for each startup mode.
- Prefer 'earliest'/'latest' when a precise offset is not needed.
When it happens
Trigger: Creating a Kinesis source with WITH option `scan.startup.mode = 'timestamp'` while omitting `scan.startup.timestamp.millis`.
Common situations: Users copy a config template that enables timestamp mode but forget the companion timestamp field; SQL changed via ALTER SOURCE adds the mode without adding the property; config validation passes because the mode value is valid but the pairing is only checked at reader construction.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- invalid scan.startup.mode, accept earliest/latest/timestamp
- error building Kinesis client
- failed to list kinesis shards
- failed to send records. sent
- failed to send records. sent
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/fade0ffd791a38c9.
Report an issue: GitHub.
Appendix: source
Thrown at src/connector/src/source/kinesis/source/reader.rs:91
parser_config: ParserConfig,
source_ctx: SourceContextRef,
_columns: Option<Vec<Column>>,
) -> Result<Self> {
assert!(splits.len() == 1);
let split = splits.into_iter().next().unwrap();
let next_offset = match &split.next_offset {
KinesisOffset::None => match &properties.scan_startup_mode {
None => KinesisOffset::Earliest,
Some(mode) => match mode.as_str() {
"earliest" => KinesisOffset::Earliest,
"latest" => KinesisOffset::Latest,
"timestamp" => {
if let Some(ts) = &properties.start_timestamp_millis {
KinesisOffset::Timestamp(*ts)
} else {
bail!("scan.startup.timestamp.millis is required");
}
}
_ => {
bail!("invalid scan.startup.mode, accept earliest/latest/timestamp")
}
},
},
next_offset => next_offset.to_owned(),
};
if !matches!(next_offset, KinesisOffset::Timestamp(_))
&& properties.start_timestamp_millis.is_some()
{
// cannot bail! here because all new split readers will fail to start if user set 'scan.startup.mode' to 'timestamp'
tracing::warn!(
"scan.startup.mode needs to be set to 'timestamp' if you want to start with a specific timestamp, starting shard {} from the beginning",
split.id()
);View on GitHub (pinned to 6469eb736d)