{"record":{"id":"8e28557cc95992b7","repo":"xai-org/grok-build","slug":"resources-persistence-writer-dropped-acknowledgeme-8e2855","errorCode":null,"errorMessage":"resources persistence writer dropped acknowledgement","messagePattern":"resources persistence writer dropped acknowledgement","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-tools/src/persistence.rs","lineNumber":180,"sourceCode":"            .send(ResourcesPersistenceCommand::SaveAndFlush {\n                snapshot,\n                respond_to,\n            })\n            .map_err(|_| {\n                io::Error::new(\n                    io::ErrorKind::BrokenPipe,\n                    \"resources persistence writer stopped\",\n                )\n            })?;\n        Ok(response)\n    }\n\n    /// Await an acknowledgement returned by [`Self::enqueue_save_and_flush`].\n    pub async fn await_save_and_flush(\n        response: tokio::sync::oneshot::Receiver<io::Result<()>>,\n    ) -> io::Result<()> {\n        response.await.map_err(|_| {\n            io::Error::new(\n                io::ErrorKind::BrokenPipe,\n                \"resources persistence writer dropped acknowledgement\",\n            )\n        })?\n    }\n\n    /// Replace pending snapshots, write this snapshot, and await the result.\n    pub async fn save_and_flush(&self, snapshot: serde_json::Value) -> io::Result<()> {\n        Self::await_save_and_flush(self.enqueue_save_and_flush(snapshot)?).await\n    }\n\n    /// `None` when this handle writes nothing.\n    pub fn state_path(&self) -> Option<&std::path::Path> {\n        self.state_path.as_deref()\n    }\n\n    /// Flush pending writes. Call on graceful shutdown.\n    pub async fn flush(&self) {","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-tools/src/persistence.rs#L162-L198","documentation":"await_save_and_flush awaits the oneshot receiver returned by enqueue_save_and_flush; if the sender side is dropped without replying, it maps the RecvError to BrokenPipe with \"resources persistence writer dropped acknowledgement\". Unlike error 706 (send failed), here the command was delivered but the writer never sent back a result, so durability is unknown.","triggerScenarios":"Calling await_save_and_flush when the writer task died between receiving the command and sending the acknowledgement — panic during serialization/replace, task abort, or runtime shutdown mid-flush.","commonSituations":"Process shutdown/ctrl-C racing an in-flight save; a panic in the writer's write loop; aborting the writer task in tests or during teardown while a save is pending.","solutions":["Treat the result as indeterminate: verify on next startup whether the snapshot actually landed on disk.","Inspect the writer task for panics during prepare_write/replace_state_path and fix the root cause.","Retry the save once a healthy writer is available.","Ensure graceful shutdown drains in-flight saves and sends acknowledgements before stopping the writer."],"exampleFix":"// before\nResourcesPersistence::await_save_and_flush(rx).await?; // assume durable\n// after\nif let Err(e) = ResourcesPersistence::await_save_and_flush(rx).await {\n    if e.kind() == std::io::ErrorKind::BrokenPipe {\n        tracing::error!(\"ack lost; snapshot durability unknown, will verify on restart\");\n        schedule_reconciliation();\n    } else {\n        return Err(e);\n    }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match ResourcesPersistence::await_save_and_flush(rx).await {\n    Ok(()) => {},\n    Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {\n        // durability unknown: verify file on disk and/or retry\n        if !state_file_exists_and_valid(&path).await { retry_save().await?; }\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Never abort the writer task while saves are pending.","Use a shutdown barrier so acknowledgements are sent before teardown.","Verify snapshot files on disk at startup to recover from lost acknowledgements.","Add tests simulating writer cancellation mid-save."],"tags":["persistence","broken-pipe","oneshot","durability"],"backgroundTag":"persistence-ack-lost","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}