{"record":{"id":"6463b1fcedcc2875","repo":"jdx/mise","slug":"executable-identity-cache-contains-too-many-entrie","errorCode":null,"errorMessage":"executable identity cache contains too many entries","messagePattern":"executable identity cache contains too many entries","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/mise-cache-core/src/agent.rs","lineNumber":1713,"sourceCode":"            .cloned();\n        Ok(AgentResponse::ExecutableIdentity { stdout })\n    }\n\n    fn store_executable_identity(\n        &self,\n        executable: PathBuf,\n        environment: BTreeMap<String, Option<String>>,\n        stdout: Vec<u8>,\n    ) -> Result<AgentResponse> {\n        if stdout.len() > MAX_EXECUTABLE_IDENTITY_SIZE {\n            bail!(\"executable identity exceeds {MAX_EXECUTABLE_IDENTITY_SIZE} bytes\");\n        }\n        let key = self.executable_identity_key(executable, environment)?;\n        let mut identities = self.executable_identities.lock().unwrap();\n        let is_new = !identities.contains_key(&key);\n        let previous_size = identities.get(&key).map_or(0, Vec::len);\n        if is_new && identities.len() >= MAX_EXECUTABLE_IDENTITIES {\n            bail!(\"executable identity cache contains too many entries\");\n        }\n        let retained_bytes = identities.values().map(Vec::len).sum::<usize>();\n        if retained_bytes - previous_size + stdout.len() > MAX_EXECUTABLE_IDENTITY_BYTES {\n            bail!(\"executable identity cache contains too many bytes\");\n        }\n        identities.insert(key, stdout.clone());\n        Ok(AgentResponse::ExecutableIdentity {\n            stdout: Some(stdout),\n        })\n    }\n\n    /// Serve newline-delimited protocol requests on an authenticated session stream.\n    pub async fn handle_connection<S>(&self, stream: S) -> Result<()>\n    where\n        S: AsyncRead + AsyncWrite + Unpin,\n    {\n        let (reader, mut writer) = tokio::io::split(stream);\n        let mut lines = BufReader::new(reader).lines();","sourceCodeStart":1695,"sourceCodeEnd":1731,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/crates/mise-cache-core/src/agent.rs#L1695-L1731","documentation":"store_executable_identity caps the in-memory identity cache at MAX_EXECUTABLE_IDENTITIES (64) entries. The cap is checked only when inserting a NEW key; overwriting an existing key never trips it.","triggerScenarios":"A session probing 65+ distinct (executable, RUSTUP_*) identity combinations — e.g. many toolchain paths or rustup shims resolved to different binaries.","commonSituations":"Enumerating every binary in a toolchain dir; multi-toolchain workspaces probing rustc from many install roots in one session.","solutions":["Limit probing to the few executables actually used for compilation","Reuse one resolved toolchain per session instead of probing many paths","Restart the session to reset the in-memory cache if it filled with one-off probes"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const MAX_IDENTITIES: usize = 64;\nlet mut probed: HashSet<ExecutableIdentityKey> = HashSet::new();\nfn should_probe(probed: &HashSet<ExecutableIdentityKey>, key: &ExecutableIdentityKey) -> bool {\n    probed.contains(key) || probed.len() < MAX_IDENTITIES\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Resolve the toolchain once per session and probe only that executable","Reuse stored identities for repeated lookups instead of re-probing variants","Remember the cache is in-memory: a session restart clears it"],"tags":["mise-cache","executable-identity","cache-limit"],"backgroundTag":"cache-capacity-exceeded","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}