risingwavelabs/risingwave · error · ConnectorError
No allow_alter_on_fly fields registered for sink
Error message
No allow_alter_on_fly fields registered for sink: {sink_name} What it means
Raised when the sink name resolves (or is JdbcSink) but neither CONNECTION_ALLOW_ALTER_ON_FLY_FIELDS nor SINK_ALLOW_ALTER_ON_FLY_FIELDS contains an entry for it — no fields registered as alterable on the fly for this sink.
Solutions
- Re-run the code generation that builds SINK_ALLOW_ALTER_ON_FLY_FIELDS.
- Add allow_alter_on_fly fields to the sink definition and regenerate if it should support them.
- Bypass this validation for sinks with no registered fields.
Example fix
// before
check_sink_allow_alter_on_fly_fields(sink, fields)?;
// after
match sink_allow_alter_fields(sink) {
Some(_) => check_sink_allow_alter_on_fly_fields(sink, fields)?,
None => {} // sink does not support on-the-fly alterations
} Defensive patterns
Strategy: type-guard
Validate before calling
fn sink_has_alter_fields(name: &str) -> bool {
if name == JdbcSink::SINK_NAME {
return CONNECTION_ALLOW_ALTER_ON_FLY_FIELDS.get(JdbcSink::SINK_NAME).is_some();
}
sink_properties::sink_name_to_config_type_name(name)
.and_then(|t| SINK_ALLOW_ALTER_ON_FLY_FIELDS.get(t))
.is_some()
} Try / catch
if sink_has_alter_fields(sink) {
check_sink_allow_alter_on_fly_fields(sink, fields)?;
} Prevention
- Re-run generation after adding sinks
- Add a test that every registered sink has an allow-list entry or is explicitly exempt
When it happens
Trigger: Calling check_sink_allow_alter_on_fly_fields with a valid sink name lacking a generated allow-list entry (generator not run, stale generated code, or sink intentionally has none).
Common situations: Newly added sink without regenerated maps; cached build missing updated generated code; calling the check for a sink that does not support on-the-fly field alterations.
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
- No allow_alter_on_fly fields registered for connection
- No allow_alter_on_fly fields registered for connector
- ALTER SINK_RATE_LIMIT is not for sink into table
- ambiguous auth: multiple auth options provided; remove one…
- auth.method=key_pair_file must not set `password`
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/ad191d5a7d8c8651.
Report an issue: GitHub.
Appendix: source
Thrown at src/connector/src/with_options_test.rs:865
) -> crate::error::ConnectorResult<()> {{
// TODO(#24846): JDBC sink currently uses `()` as sink config type in `for_all_sinks!`,
// so it cannot have an isolated key in `SINK_ALLOW_ALTER_ON_FLY_FIELDS`.
// Reuse the JDBC entry in `CONNECTION_ALLOW_ALTER_ON_FLY_FIELDS` for now.
// TODO(#24846): remove this special case after JDBC sink has a dedicated config type
// and allow-alter fields are generated directly into `SINK_ALLOW_ALTER_ON_FLY_FIELDS`.
let allowed_fields = if sink_name == JdbcSink::SINK_NAME {{
CONNECTION_ALLOW_ALTER_ON_FLY_FIELDS.get(JdbcSink::SINK_NAME)
}} else {{
// Convert sink name to the type name key
let Some(type_name) = sink_properties::sink_name_to_config_type_name(sink_name) else {{
return Err(ConnectorError::from(anyhow::anyhow!(
"Unknown sink connector: {{sink_name}}"
)));
}};
SINK_ALLOW_ALTER_ON_FLY_FIELDS.get(type_name)
}};
let Some(allowed_fields) = allowed_fields else {{
return Err(ConnectorError::from(anyhow::anyhow!(
"No allow_alter_on_fly fields registered for sink: {{sink_name}}"
)));
}};
for field in fields {{
if !allowed_fields.contains(field) {{
return Err(ConnectorError::from(anyhow::anyhow!(
"Field '{{field}}' is not allowed to be altered on the fly for sink: {{sink_name}}"
)));
}}
}}
Ok(())
}}
"#,
source_entries = source_entries,
sink_entries = sink_entries
)
}
View on GitHub (pinned to 6469eb736d)