{"record":{"id":"58b92f7c230e580c","repo":"GitoxideLabs/gitoxide","slug":"the-tempfile-with-id-wasn-t-available-anymore","errorCode":null,"errorMessage":"The tempfile with id {} wasn't available anymore","messagePattern":"The tempfile with id (.+?) wasn't available anymore","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix-tempfile/src/handle.rs","lineNumber":191,"sourceCode":"        res.and_then(|(_k, v)| v.map(|v| v.into_tempfile().expect(\"correct runtime typing\")))\n    }\n\n    /// Close the underlying file handle but keep track of the temporary file as before for automatic cleanup.\n    ///\n    /// This saves system resources in situations where one opens a tempfile file at a time, writes a new value, and closes\n    /// it right after to perform more updates of this kind in other tempfiles. When all succeed, they can be renamed one after\n    /// another.\n    pub fn close(self) -> std::io::Result<Handle<Closed>> {\n        match REGISTRY.remove(&self.id) {\n            Some((id, Some(t))) => {\n                std::mem::forget(self);\n                expect_none(REGISTRY.insert(id, Some(t.close())));\n                Ok(Handle::<Closed> {\n                    id,\n                    _marker: Default::default(),\n                })\n            }\n            None | Some((_, None)) => Err(std::io::Error::new(\n                std::io::ErrorKind::NotFound,\n                format!(\"The tempfile with id {} wasn't available anymore\", self.id),\n            )),\n        }\n    }\n}\n\n/// Mutation\nimpl Handle<Writable> {\n    /// Obtain a mutable handler to the underlying named tempfile and call `f(&mut named_tempfile)` on it.\n    ///\n    /// Note that for the duration of the call, a signal interrupting the operation will cause the tempfile not to be cleaned up\n    /// as it is not visible anymore to the signal handler.\n    ///\n    /// # Assumptions\n    /// The caller must assure that the signal handler for cleanup will be followed by an abort call so that\n    /// this code won't run again on a removed instance. An error will occur otherwise.\n    pub fn with_mut<T>(&mut self, once: impl FnOnce(&mut NamedTempFile) -> T) -> std::io::Result<T> {","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-tempfile/src/handle.rs#L173-L209","documentation":"Returned by `Handle::close()` when the tempfile backing this handle is no longer present in the global registry. The registry entry is either gone (removed) or its slot holds `None`, which happens after the handle was already closed, taken, or the registry entry was consumed. The library throws this to prevent double-close/use-after-close on tempfile handles.","triggerScenarios":"Calling `close()` on a `Handle` that was already closed, or on a handle whose registry entry was consumed (e.g. via `take()`/persist), or after the registry entry was dropped.","commonSituations":"Closing the same tempfile handle twice in error-recovery paths; persisting a tempfile (which consumes it) and then calling `close()` on the stale handle; sharing a handle across threads where one side closes it first.","solutions":["Ensure `close()` is called at most once per handle, e.g. via `Option<Handle>` and `.take()`","Restructure code so ownership of the handle makes double-close impossible (move the handle into the closing scope)","If persisting, use `persist()` instead of `close()` and do not reuse the handle afterwards"],"exampleFix":"// before\nhandle.close()?;\n// ...\nhandle.close()?; // NotFound: already closed\n// after\nif let Some(handle) = handle_opt.take() {\n    handle.close()?;\n}","handlingStrategy":"try-catch","validationCode":"// Rust: only close when the handle is still owned/open\nfn close_once(handle: &mut Option<gix_tempfile::Handle<gix_tempfile::Closed>>) -> std::io::Result<()> {\n    // a Closed-typed handle cannot call close(); None means already handled\n    let _ = handle;\n    Ok(())\n}","typeGuard":"fn is_open(h: &Option<gix_tempfile::Handle<gix_tempfile::Open>>) -> bool { h.is_some() }","tryCatchPattern":"match handle.take() {\n    Some(h) => match h.close() {\n        Ok(_) => {},\n        Err(e) if e.kind() == std::io::ErrorKind::NotFound => { /* already closed; treat as idempotent */ },\n        Err(e) => return Err(e),\n    },\n    None => { /* already closed */ }\n}","preventionTips":["Model handle lifetime with typestate (Open/Closed) so double-close cannot compile","Wrap handles in Option and .take() before closing","Never store handles long-term; use them in a scope and close/drop at the end"],"tags":["rust","tempfile","use-after-close","io"],"backgroundTag":"resource-not-found","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}