{"record":{"id":"cec947867997db93","repo":"risingwavelabs/risingwave","slug":"missing-system-param","errorCode":null,"errorMessage":"missing system param {:?}","messagePattern":"missing system param (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/meta/src/controller/system_param.rs","lineNumber":86,"sourceCode":"                }\n            });\n            derive_missing_fields(&mut params);\n            if !models.is_empty() {\n                let unrecognized_params = models.into_iter().map(|model| model.name).collect::<Vec<_>>();\n                tracing::warn!(\"unrecognized system params {:?}\", unrecognized_params);\n            }\n            Ok(params)\n        }\n    };\n}\n\n/// Derive serialization to db models.\nmacro_rules! impl_system_params_to_models {\n    ($({ $field:ident, $type:ty, $default:expr, $is_mutable:expr, $($rest:tt)* },)*) => {\n        #[expect(deprecated)]\n        #[allow(clippy::vec_init_then_push)]\n        pub fn system_params_to_model(params: &PbSystemParams) -> MetaResult<Vec<system_parameter::ActiveModel>> {\n            check_missing_params(params).map_err(|e| anyhow!(e))?;\n            let mut models = Vec::new();\n            $(\n                let value = params.$field.as_ref().unwrap().to_string();\n                models.push(system_parameter::ActiveModel {\n                    name: Set(key_of!($field).to_string()),\n                    value: Set(value),\n                    is_mutable: Set($is_mutable),\n                    description: Set(None),\n                });\n            )*\n            Ok(models)\n       }\n    };\n}\n\n// For each field in `persisted` and `init`\n// 1. Some, None: The persisted field is deprecated, so just ignore it.\n// 2. Some, Some: Check equality and warn if they differ.","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/meta/src/controller/system_param.rs#L68-L104","documentation":"This error comes from `check_missing_params`, invoked inside `system_params_to_model`, which derives the persisted system-parameter rows from a `PbSystemParams` protobuf. Every system parameter field must be `Some` before serialization; if any field is `None` the macro-generated code aborts with \"missing system param {:?}\". It is an internal invariant: the meta service refuses to persist a partial set of system parameters to the database.","triggerScenarios":"Calling `system_params_to_model` with a `PbSystemParams` whose optional proto fields are unset (e.g. params loaded from an older cluster version, or a manually constructed `PbSystemParams` missing fields).","commonSituations":"Rolling upgrades where new parameters were introduced and stored snapshots lack them without a migration; tools or tests that build `PbSystemParams` by hand and forget to fill in all fields; a corrupted/edited system_parameter table combined with incomplete defaults.","solutions":["Ensure every optional field of `PbSystemParams` is populated before serialization — start from the documented defaults (`SystemParams::default()` / example config) and merge, rather than constructing a bare proto.","Merge persisted DB params over a complete default set (see `merge_params` usage in `SystemController::new`) so missing fields are backfilled with defaults.","If this happens after a version upgrade, run the upgrade path that seeds newly introduced parameters instead of loading the raw DB rows directly.","Check `check_missing_params` output — it names the missing field — and set that parameter explicitly (ALTER SYSTEM / bootstrap config)."],"exampleFix":"// before\nlet params: PbSystemParams = read_from_db_only();\nsystem_params_to_model(&params)?;\n// after\nlet params = merge_params(system_params_from_db(db_params)?, PbSystemParams::default());\nsystem_params_to_model(&params)?;","handlingStrategy":"validation","validationCode":"fn ensure_params_complete(p: &PbSystemParams) -> Result<(), String> {\n    let missing: Vec<&str> = [\n        (\"backup_config\", p.backup_config.is_none()),\n        (\"barrier_interval\", p.barrier_interval.is_none()),\n    ].iter().filter(|(_, m)| *m).map(|(n, _)| *n).collect();\n    if missing.is_empty() { Ok(()) } else { Err(format!(\"missing: {:?}\", missing)) }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always build PbSystemParams from SystemParams::default() and merge, never construct empty protos","After upgrades, run the parameter backfill/migration before loading raw DB rows","Log the result of check_missing_params during bootstrap to catch gaps early"],"tags":["meta","system-params","invariant"],"backgroundTag":"missing-required-config-field","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}