risingwavelabs/risingwave · error · SinkError::Config
invalid write_mode: {}, must be one of: {}, {}
Error message
invalid write_mode: {}, must be one of: {}, {} What it means
This is the FromStr parser for the `IcebergWriteMode` sink option. It only accepts the exact strings defined by ICEBERG_WRITE_MODE_MERGE_ON_READ ("merge-on-read") and ICEBERG_WRITE_MODE_COPY_ON_WRITE ("copy-on-write"); any other value for the `write_mode` connector property fails sink validation with this config error. It is thrown at sink creation time before any data is written.
Source
Thrown at src/connector/src/sink/iceberg/config.rs:75
}
impl IcebergWriteMode {
pub fn as_str(self) -> &'static str {
match self {
IcebergWriteMode::MergeOnRead => ICEBERG_WRITE_MODE_MERGE_ON_READ,
IcebergWriteMode::CopyOnWrite => ICEBERG_WRITE_MODE_COPY_ON_WRITE,
}
}
}
impl std::str::FromStr for IcebergWriteMode {
type Err = SinkError;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
match s {
ICEBERG_WRITE_MODE_MERGE_ON_READ => Ok(IcebergWriteMode::MergeOnRead),
ICEBERG_WRITE_MODE_COPY_ON_WRITE => Ok(IcebergWriteMode::CopyOnWrite),
_ => Err(SinkError::Config(anyhow!(format!(
"invalid write_mode: {}, must be one of: {}, {}",
s, ICEBERG_WRITE_MODE_MERGE_ON_READ, ICEBERG_WRITE_MODE_COPY_ON_WRITE
)))),
}
}
}
impl TryFrom<&str> for IcebergWriteMode {
type Error = <Self as std::str::FromStr>::Err;
fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
value.parse()
}
}
impl TryFrom<String> for IcebergWriteMode {
type Error = <Self as std::str::FromStr>::Err;
View on GitHub (pinned to 6469eb736d)
Solutions
- Set write_mode to exactly 'merge-on-read' or 'copy-on-write' in the WITH clause
- Remove the write_mode option entirely to use the default value
- Check the connector documentation for the accepted literal strings (case-sensitive)
- Run SHOW CREATE SINK or the sink error message to confirm which invalid value was passed
Example fix
// before WITH (connector = 'iceberg', write_mode = 'merge_on_read') // after WITH (connector = 'iceberg', write_mode = 'merge-on-read')
Defensive patterns
Strategy: validation
Validate before calling
const VALID_WRITE_MODES: [&str; 2] = ["merge-on-read", "copy-on-write"];
fn validate_write_mode(mode: &str) -> Result<(), String> {
if VALID_WRITE_MODES.contains(&mode) {
Ok(())
} else {
Err(format!(
"invalid write_mode: {}, must be one of: merge-on-read, copy-on-write",
mode
))
}
} Type guard
fn is_valid_write_mode(s: &str) -> bool {
matches!(s, "merge-on-read" | "copy-on-write")
} Try / catch
match s.parse::<IcebergWriteMode>() {
Ok(mode) => mode,
Err(e) => {
// SinkError::Config: fix the WITH option string before retrying
return Err(e.context("check write_mode in WITH clause: exact literal required"));
}
} Prevention
- Use the exact literals 'merge-on-read' / 'copy-on-write' (kebab-case, lowercase)
- Copy WITH options from RisingWave docs, not other engines' connector docs
- Validate connector options with a dry-run/plan before CREATE SINK in CI
- Omit write_mode when the default is acceptable
When it happens
Trigger: A CREATE SINK ... WITH (connector='iceberg', write_mode='...') statement supplies a write_mode string that is not exactly 'merge-on-read' or 'copy-on-write' (typo, wrong case, extra whitespace, or a value from another system such as 'mor' or 'upsert').
Common situations: Copy-pasting options from a different engine's iceberg connector docs; misspelling like 'merge_on_read' with underscores; using quotes/case variants like 'MergeOnRead'; renaming options during a version upgrade.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- invalid compaction_type: {}, must be one of: {}, {}, {}, {}
- 'copy-on-write' mode is not supported for append-only iceber
- creating an Iceberg table with VARIANT column `{}` requires
- Invalid warehouse path: {}
- Partition source column does not exist in schema: {}
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/7762ecec60a411bd.
Report an issue: GitHub.