spacedriveapp/spacedrive · error · anyhow::Error
Failed to finish stream: {}
Error message
Failed to finish stream: {} What it means
After all chunks and the completion message were sent, send_stream.finish() failed - the QUIC FIN could not be queued because the connection broke in the window after the last flush. The transfer outcome is now unknown: the receiver may hold all data but never saw a clean end-of-stream. The sender fails the job rather than assume success.
Source
Thrown at core/src/ops/files/copy/strategy.rs:1278
total_bytes: bytes_transferred,
};
let completion_data = rmp_serde::to_vec(&completion_message)?;
send_stream.write_u8(0).await?;
send_stream
.write_all(&(completion_data.len() as u32).to_be_bytes())
.await?;
send_stream.write_all(&completion_data).await?;
send_stream.flush().await?;
ctx.log(format!(
"Completion message sent, waiting for final acknowledgment from receiver"
));
send_stream
.finish()
.map_err(|e| anyhow::anyhow!("Failed to finish stream: {}", e))?;
ctx.log("Waiting for TransferFinalAck from receiver...".to_string());
let mut msg_type = [0u8; 1];
recv_stream.read_exact(&mut msg_type).await?;
if msg_type[0] != 0 {
return Err(anyhow::anyhow!("Unexpected response type: {}", msg_type[0]));
}
let mut len_buf = [0u8; 4];
recv_stream.read_exact(&mut len_buf).await?;
let msg_len = u32::from_be_bytes(len_buf) as usize;
let mut msg_buf = vec![0u8; msg_len];
recv_stream.read_exact(&mut msg_buf).await?;
let ack_message: crate::service::network::protocol::file_transfer::FileTransferMessage =View on GitHub (pinned to 6dfeccf211)
Solutions
- Retry the copy - the receiver discards an unfinished stream on its side
- Check the peer for crashes or resource pressure while processing the completion message
- If it recurs at the very end of large transfers, check peer memory and disk pressure
- Verify network stability across the full transfer duration
Defensive patterns
Strategy: retry
Try / catch
// finish() failure means unknown outcome; only a full retry can confirm delivery.
match complete_transfer().await {
Ok(()) => Ok(()),
Err(ref e) if e.to_string().contains("finish") => {
tracing::warn!(error = %e, "stream FIN failed; receiver will discard, retrying");
complete_transfer().await
}
Err(e) => Err(e.clone()),
} Prevention
- Check peer health before starting very large transfers
- Treat a failed FIN as a failed transfer - never assume delivery
When it happens
Trigger: Connection dropped immediately after the completion message was flushed; peer reset the connection upon receiving it; network change between the final write and finish().
Common situations: Last-instant disconnects at the end of long transfers, peer crashing while handling the completion message.
Related errors
- Failed to open stream: {}
- Failed to write message length: {}
- Failed to write chunk data: {}
- Failed to flush stream: {}
- Expected TransferFinalAck, got different message type
AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16).
Data as JSON: /api/errors/970d91c5918fb117.
Report an issue: GitHub.