{"record":{"id":"ec82ebd65c1b9a73","repo":"neondatabase/neon","slug":"incompatible-resource-multipler-and-spread-factor","errorCode":null,"errorMessage":"incompatible resource_multipler and spread_factor","messagePattern":"incompatible resource_multipler and spread_factor","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"libs/vm_monitor/src/filecache.rs","lineNumber":114,"sourceCode":"        // and\n        //\n        //   size = `resource_multiplier` × total\n        //\n        // .. where `total` is the total resources. These are isomorphic to the typical 'y = mx + b'\n        // form, with y = \"size\" and x = \"total\".\n        //\n        // These lines intersect at:\n        //\n        //               `min_remaining_after_cache`\n        //   ———————————————————————————————————————————————————\n        //    1 - `resource_multiplier` × (`spread_factor` + 1)\n        //\n        // We want to ensure that this value (a) exists, and (b) is >= `min_remaining_after_cache`. This is\n        // guaranteed when '`resource_multiplier` × (`spread_factor` + 1)' is less than 1.\n        // (We also need it to be >= 0, but that's already guaranteed.)\n\n        let intersect_factor = self.resource_multiplier * (self.spread_factor + 1.0);\n        anyhow::ensure!(\n            intersect_factor < 1.0,\n            \"incompatible resource_multipler and spread_factor\"\n        );\n        Ok(())\n    }\n\n    /// Calculate the desired size of the cache, given the total memory\n    pub fn calculate_cache_size(&self, total: u64) -> u64 {\n        // *Note*: all units are in bytes, until the very last line.\n        let available = total.saturating_sub(self.min_remaining_after_cache.get());\n        if available == 0 {\n            return 0;\n        }\n\n        // Conversions to ensure we don't overflow from floating-point ops\n        let size_from_spread =\n            i64::max(0, (available as f64 / (1.0 + self.spread_factor)) as i64) as u64;\n","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/neondatabase/neon/blob/8f60b04da47ffefe0e52bda2440134b42874eb75/libs/vm_monitor/src/filecache.rs#L96-L132","documentation":"Thrown during FileCache config validation in the Neon autoscaling vm-monitor. The cache-sizing algorithm splits total memory along two lines whose intersection must exist and stay at or above `min_remaining_after_cache`; that is only guaranteed when `resource_multiplier * (spread_factor + 1.0) < 1.0`. The `ensure!` fires when the two coupled config values violate this invariant, making the size formula unsolvable.","triggerScenarios":"Validating a `FileCache` config where the pair is too large together, e.g. `resource_multiplier = 0.9` with `spread_factor = 0.5` gives 0.9 × (0.5 + 1.0) = 1.35 ≥ 1.0 and bails. Any pair where the product with (spread_factor + 1) reaches or exceeds 1.0 triggers it.","commonSituations":"Hand-tuning vm-monitor memory settings; raising `spread_factor` to smooth cache growth without lowering `resource_multiplier`; copying configs between environments with different memory budgets.","solutions":["Lower `resource_multiplier` so that `resource_multiplier * (spread_factor + 1.0) < 1.0` (e.g. with spread_factor 0.5, keep the multiplier below ~0.667)","Or lower `spread_factor`; at spread_factor 0.0 the multiplier only needs to be < 1.0","Revert to the shipped/default vm-monitor file cache configuration for your deployment","Add a config sanity test in CI that runs the same intersect-factor check"],"exampleFix":"// before — fails validation: 0.9 * (0.5 + 1.0) = 1.35 >= 1.0\nconfig.resource_multiplier = 0.9;\nconfig.spread_factor = 0.5;\n\n// after — passes: 0.5 * (0.5 + 1.0) = 0.75 < 1.0\nconfig.resource_multiplier = 0.5;\nconfig.spread_factor = 0.5;","handlingStrategy":"validation","validationCode":"if config.resource_multiplier * (config.spread_factor + 1.0) >= 1.0 {\n    return Err(anyhow::anyhow!(\n        \"refusing to start: resource_multiplier * (spread_factor + 1) must be < 1.0\"\n    ));\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat resource_multiplier and spread_factor as one coupled pair and validate their product wherever config is loaded","Add a CI test over deployed config files running the same intersect-factor check","Keep a table of known-good (multiplier, spread) pairs next to deployment configs"],"tags":["rust","neon","vm-monitor","config","validation"],"backgroundTag":"config-validation-failed","analyzedSha":"8f60b04da47ffefe0e52bda2440134b42874eb75","analyzedAt":"2026-08-16T23:39:28.135Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}