{"record":{"id":"feeb24b033f7e7c0","repo":"risingwavelabs/risingwave","slug":"specify-at-most-one-of-start-offset-or-start-snaps","errorCode":null,"errorMessage":"specify at most one of start_offset or start_snapshot","messagePattern":"specify at most one of start_offset or start_snapshot","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/connector/src/source/google_pubsub/enumerator/client.rs","lineNumber":73,"sourceCode":"            .exists(None)\n            .await\n            .context(\"error checking subscription validity\")?\n        {\n            bail!(\"subscription {} does not exist\", &sub.id())\n        }\n\n        let seek_to = match (properties.start_offset, properties.start_snapshot) {\n            (None, None) => None,\n            (Some(start_offset), None) => {\n                let ts = start_offset\n                    .parse::<i64>()\n                    .context(\"error parsing start_offset\")\n                    .map(|nanos| Utc.timestamp_nanos(nanos).into())?;\n                Some(SeekTo::Timestamp(ts))\n            }\n            (None, Some(snapshot)) => Some(SeekTo::Snapshot(snapshot)),\n            (Some(_), Some(_)) => {\n                bail!(\"specify at most one of start_offset or start_snapshot\")\n            }\n        };\n\n        if let Some(seek_to) = seek_to {\n            sub.seek(seek_to, None)\n                .await\n                .context(\"error seeking subscription\")?;\n        }\n\n        Ok(Self {\n            subscription: properties.subscription,\n        })\n    }\n\n    async fn list_splits(&mut self) -> ConnectorResult<Vec<PubsubSplit>> {\n        tracing::debug!(\"enumerating pubsub splits (adaptive mode, returning 1 template split)\");\n        Ok(vec![PubsubSplit {\n            index: 0,","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/source/google_pubsub/enumerator/client.rs#L55-L91","documentation":"PubSub supports seeking either to a timestamp (start_offset) or to a named snapshot (start_snapshot), but not both at once. The enumerator's SeekTo resolution bails if both properties are provided simultaneously. Exactly one of the two must be set (or neither).","triggerScenarios":"Creating a PubSub source with both `start_offset` and `start_snapshot` specified in the WITH clause, hitting the (Some(_), Some(_)) match arm in PubsubEnumeratorClient::new.","commonSituations":"Copy-pasting a config template that already had start_snapshot and adding start_offset on top; trying to 'be safe' by specifying both; leftover flags from an incremental config edit.","solutions":["Remove `start_snapshot` if you want time-based recovery via `start_offset`.","Remove `start_offset` if you want snapshot-based recovery via `start_snapshot`.","Omit both if you want to resume from the subscription's current state (default)."],"exampleFix":"-- before\nWITH (connector = 'google_pubsub', start_offset = '2024-01-01T00:00:00Z', start_snapshot = 'my-snap')\n-- after (keep only one)\nWITH (connector = 'google_pubsub', start_offset = '2024-01-01T00:00:00Z')","handlingStrategy":"validation","validationCode":"// reject configs specifying both\nfunction pubsubSeekPropsValid(p) {\n  return !(p.start_offset && p.start_snapshot);\n}","typeGuard":"function hasNoConflictingSeek(p) {\n  return !(\"start_offset\" in p && \"start_snapshot\" in p);\n}","tryCatchPattern":"if (props.start_offset && props.start_snapshot) {\n  throw new Error(\"specify at most one of start_offset or start_snapshot\");\n}","preventionTips":["Decide on one recovery strategy (timestamp or snapshot) per source.","Review the full WITH clause when editing configs incrementally.","Encode the exclusivity in config validation tooling/CI for source DDL."],"tags":["gcp","pubsub","configuration","conflicting-options"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T21:17:11.552Z"}