astrid-runtime/astrid · error · io::Error

staged content writer is closed

Error message

staged content writer is closed

What it means

The staged content writer was used after being closed, so the library returns a BrokenPipe io::Error. The writer's close operation releases its reservation (reserved_identifiers removal), and any subsequent operation has no valid backing state, so it fails rather than silently dropping data.

Solutions

  1. Remove the write call that occurs after close(), or move it before closing
  2. Restructure code so the writer is consumed in a linear order: write all data, then close once
  3. Wrap the writer so Rust ownership prevents reuse after close (consume self in close)
  4. Check application logic for double-close paths (error + success cleanup both closing)

Example fix

// before
writer.write_all(&chunk)?; // after close()
writer.close()?;
writer.write_all(&more)?;
// after
writer.write_all(&chunk)?;
writer.write_all(&more)?;
writer.close()?;
Defensive patterns

Strategy: try-catch

Validate before calling

// Rust: track closed state in a wrapper
struct GuardedWriter { w: Option<StagedContentWriter> }
impl GuardedWriter {
    fn write(&mut self, b: &[u8]) -> io::Result<()> {
        match &mut self.w { Some(w) => w.write_all(b), None => Ok(()) } // no-op after close
    }
}

Type guard

fn is_open(w: &StagedWriterHandle) -> bool { !w.is_closed() } // expose/check a closed flag before use

Try / catch

match writer.write_all(&data) {
    Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => { /* writer already closed: drop or reopen */ }
    other => other?,
}

Prevention

When it happens

Trigger: Calling any write/flush method on a StagedContentWriter after close() has been called, e.g. writing in two phases where the second write happens after an early close, or reusing a stored writer handle after the close path ran.

Common situations: Wrapping the writer in a scope where close is called then more bytes are appended; double-close followed by use; holding the writer in a struct and using it after a cleanup routine closed it.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/ae2d9e99b18c0160. Report an issue: GitHub.

Appendix: source

Thrown at crates/astrid-storage/src/principal_state/staging/writer.rs:162

    fn drop(&mut self) {
        if self.preserve_on_drop {
            return;
        }
        self.file.take();
        if let Some(path) = self.path.take() {
            let _ = std::fs::remove_file(path);
        }
        self.area
            .inner
            .seal_order
            .lock()
            .reserved_identifiers
            .remove(&self.id);
    }
}

fn closed_writer() -> std::io::Error {
    std::io::Error::new(
        std::io::ErrorKind::BrokenPipe,
        "staged content writer is closed",
    )
}

View on GitHub (pinned to affd8760f4)