helix-editor/helix · error · anyhow::Error
failed to send save event: {}
Error message
failed to send save event: {} What it means
Editor::save funnels each document's saves through a per-document stream (self.saves). The error fires when .send(stream::once(future)) on that stream returns Err, meaning the receiving end of the save pipeline for that document is already closed. In practice the channel is closed during editor/document teardown, so a save requested in that window fails with "failed to send save event".
Source
Thrown at helix-view/src/editor.rs:2266
// When a file is written to, notify the file event handler.
// Note: This can be removed once proper file watching is implemented.
let handler = self.language_servers.file_event_handler.clone();
let future = async move {
let res = doc_save_future.await;
if let Ok(event) = &res {
handler.file_changed(event.path.clone());
}
res
};
use futures_util::stream;
self.saves
.get(&doc_id)
.ok_or_else(|| anyhow::format_err!("saves are closed for this document!"))?
.send(stream::once(Box::pin(future)))
.map_err(|err| anyhow!("failed to send save event: {}", err))?;
self.write_count += 1;
Ok(())
}
pub fn resize(&mut self, area: Rect) {
if self.tree.resize(area) {
self._refresh();
};
}
pub fn focus(&mut self, view_id: ViewId) {
if self.tree.focus == view_id {
return;
}
// Reset mode to normal and ensure any pending changes are committed in the old document.View on GitHub (pinned to 079a789e8c)
Solutions
- Ensure saves are not requested after the document or editor begins closing (check the document is still open / editor not shutting down before calling save).
- If it happens on exit with format-on-save or autosave enabled, disable those for the session or update Helix — teardown races here are worth an upstream issue if reproducible.
- For embedders, keep the event loop running until all write_count saves settle before dropping the editor.
Defensive patterns
Strategy: try-catch
Validate before calling
if !editor.saves_for_doc_open(doc_id) { // expose/check that the per-doc save stream exists
return Err(anyhow!("save pipeline already closed for {doc_id:?}"));
}
editor.save(doc_id, /* ... */)?; Try / catch
if let Err(err) = editor.save(/* ... */) {
if err.to_string().contains("failed to send save event") {
// channel closed during teardown: not retryable, surface but do not crash
log::debug!("save dropped during shutdown: {err:#}");
} else {
return Err(err);
}
} Prevention
- Do not issue saves after a document/editor close begins; sequence shutdown before write triggers.
- In embedders, drain the save pipeline before dropping the Editor.
- Treat this specific send failure as a teardown race, not a disk failure — don't misreport it to users as I/O.
When it happens
Trigger: Issuing a save (including format-on-save or write-then-close sequences) for a document whose save handler has been dropped: saving during editor shutdown, a race between closing a view/document and a pending save, or an embedder calling save after the editor event loop stopped draining saves.
Common situations: Automation or plugins that trigger writes while the editor is exiting; rapid :q with pending autosave/format-on-save; embedders (helix as a library) that shut down the event loop with saves still queued.
Related errors
- Failed to parse snippet. Remaining input: {}
- Command not provided
- Incorrect transport {}
- DAP request failed
- Git command failed. Stdout: {} Stderr: {}
AI-assisted analysis of helix-editor/helix@079a789e8c (2026-08-16).
Data as JSON: /api/errors/c7456ea3dbf7c184.
Report an issue: GitHub.