{"record":{"id":"532a746810d73232","repo":"neondatabase/neon","slug":"invalid-monitor-config-sys-buffer-bytes-cannot-be","errorCode":null,"errorMessage":"invalid monitor Config: sys_buffer_bytes cannot be 0","messagePattern":"invalid monitor Config: sys_buffer_bytes cannot be 0","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"libs/vm_monitor/src/runner.rs","lineNumber":118,"sourceCode":"        // We want our threshold to be met gracefully instead of letting postgres get OOM-killed\n        // (or if there's room, spilling to swap).\n        // So we guarantee that there's at least `cgroup_min_overhead_fraction` of total memory\n        // remaining above the threshold.\n        (total_mem as f64 * (1.0 - self.cgroup_min_overhead_fraction)) as u64\n    }\n}\n\nimpl Runner {\n    /// Create a new monitor.\n    #[tracing::instrument(skip_all, fields(?config, ?args))]\n    pub async fn new(\n        config: Config,\n        args: &Args,\n        ws: WebSocket,\n        kill: broadcast::Receiver<()>,\n        token: CancellationToken,\n    ) -> anyhow::Result<Runner> {\n        anyhow::ensure!(\n            config.sys_buffer_bytes != 0,\n            \"invalid monitor Config: sys_buffer_bytes cannot be 0\"\n        );\n\n        let dispatcher = Dispatcher::new(ws)\n            .await\n            .context(\"error creating new dispatcher\")?;\n\n        let mut state = Runner {\n            config,\n            filecache: None,\n            cgroup: None,\n            dispatcher,\n            counter: 1, // NB: must be odd, see the comment about the field for more.\n            last_upscale_request_at: None,\n            kill,\n        };\n","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/neondatabase/neon/blob/8f60b04da47ffefe0e52bda2440134b42874eb75/libs/vm_monitor/src/runner.rs#L100-L136","documentation":"`Runner::new` in the vm-monitor rejects a `Config` where `sys_buffer_bytes == 0`. That field estimates memory reserved for the system and feeds the file-cache sizing math, so zero would make the calculations meaningless. It comes from the monitor's configuration file (the `--config` argument), normally written by the Neon control plane.","triggerScenarios":"Starting the vm-monitor with a config file that omits `sys_buffer_bytes` (integer field defaults to 0 via serde) or explicitly sets it to 0.","commonSituations":"Hand-writing a dev/test config and forgetting the field; a control-plane template regression that stopped populating the key; a key-name typo or casing mismatch so serde never reads the provided value.","solutions":["Set a non-zero `sys_buffer_bytes` in the monitor's config file (order of a few hundred MiB, e.g. 400000000)","Check for typos/casing in the key so deserialization actually picks it up","Diff against a config file from a known-working deployment","If the config is generated by the control plane, verify the attached config parameters/secret"],"exampleFix":"// before (monitor config file): field missing -> defaults to 0\n{ \"period\": \"1s\", \"scaling_config\": { ... } }\n\n// after: explicit non-zero value (key name per vm_monitor Config serde schema)\n{ \"period\": \"1s\", \"sys_buffer_bytes\": 400000000, \"scaling_config\": { ... } }","handlingStrategy":"validation","validationCode":"if config.sys_buffer_bytes == 0 {\n    anyhow::bail!(\"refusing to start: sys_buffer_bytes must be set to a non-zero value in the monitor config\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate required non-zero config fields at load time, before Runner::new","Deny missing/unknown fields when deserializing monitor config to catch typos early","Smoke-test config files in CI through the same validation path"],"tags":["rust","neon","vm-monitor","config","startup"],"backgroundTag":"invalid-configuration","analyzedSha":"8f60b04da47ffefe0e52bda2440134b42874eb75","analyzedAt":"2026-08-16T23:39:28.135Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}