{"record":{"id":"16e7f9b437c317a1","repo":"quickwit-oss/quickwit","slug":"grpc-max-connection-age-grace-requires-grpc-max","errorCode":null,"errorMessage":"`grpc.max_connection_age_grace` requires `grpc.max_connection_age` to be set","messagePattern":"`grpc\\.max_connection_age_grace` requires `grpc\\.max_connection_age` to be set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"quickwit/quickwit-config/src/node_config/mod.rs","lineNumber":138,"sourceCode":"    #[serde(default = \"default_keep_alive_timeout\")]\n    pub timeout: HumanDuration,\n}\n\nimpl GrpcConfig {\n    fn default_max_message_size() -> ByteSize {\n        ByteSize::mib(20)\n    }\n\n    pub fn validate(&self) -> anyhow::Result<()> {\n        ensure!(\n            self.max_message_size >= ByteSize::mb(1),\n            \"max gRPC message size (`grpc.max_message_size`) must be at least 1MB, got `{}`\",\n            self.max_message_size\n        );\n        if let Some(tls_config) = &self.tls_config {\n            tls_config.validate()?;\n        }\n        ensure!(\n            !(self.max_connection_age_grace.is_some() && self.max_connection_age.is_none()),\n            \"`grpc.max_connection_age_grace` requires `grpc.max_connection_age` to be set\"\n        );\n        Ok(())\n    }\n}\n\nimpl Default for GrpcConfig {\n    fn default() -> Self {\n        Self {\n            max_message_size: Self::default_max_message_size(),\n            tls_config: None,\n            keep_alive: None,\n            max_connection_age: None,\n            max_connection_age_grace: None,\n        }\n    }\n}","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/quickwit-oss/quickwit/blob/a39730c5cdcd1a4fe798403737ae293999ea21f8/quickwit/quickwit-config/src/node_config/mod.rs#L120-L156","documentation":"The gRPC server config validation requires that `max_connection_age_grace` is only set together with `max_connection_age`: a grace period only makes sense as an extension of a connection's max age. Setting grace without age leaves the setting meaningless, so `GrpcConfig::validate` fails with this message.","triggerScenarios":"Setting `grpc.max_connection_age_grace` in the node config while leaving `grpc.max_connection_age` unset, then loading/validating the node config.","commonSituations":"Tuning gRPC connection recycling and only partially copying example settings; a config template where the age line was commented out but the grace line remained.","solutions":["Add `grpc.max_connection_age` alongside `max_connection_age_grace`","Remove `grpc.max_connection_age_grace` if you don't want connection aging at all","Review the gRPC config section so both values are configured together"],"exampleFix":"// before\ngrpc:\n  max_connection_age_grace: 30s\n// after\ngrpc:\n  max_connection_age: 60s\n  max_connection_age_grace: 30s","handlingStrategy":"validation","validationCode":"fn validate_grpc_age_pair(cfg: &GrpcConfig) -> anyhow::Result<()> {\n    if cfg.max_connection_age_grace.is_some() && cfg.max_connection_age.is_none() {\n        anyhow::bail!(\"grpc.max_connection_age_grace requires grpc.max_connection_age\");\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = node_config.validate() {\n    if e.to_string().contains(\"max_connection_age_grace\") {\n        eprintln!(\"Set both grpc.max_connection_age and max_connection_age_grace, or drop the grace value.\");\n    }\n}","preventionTips":["Always configure connection age and grace as a pair","Comment out both lines together when disabling connection recycling","Diff your gRPC config against the reference example before deploying"],"tags":["config","grpc","validation"],"backgroundTag":"missing-required-config-field","analyzedSha":"a39730c5cdcd1a4fe798403737ae293999ea21f8","analyzedAt":"2026-09-08T13:19:37.784Z","contentChangedAt":"2026-09-08T13:19:37.784Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}