spacedriveapp/spacedrive · info · std::io::Error
Operation cancelled
Error message
Operation cancelled
What it means
Returned by the single-file copy loop when ctx.check_interrupt() signals that the job was cancelled mid-transfer. Before returning, the code removes the partial destination file so a later resume never treats truncated data as complete, then returns io::Error with ErrorKind::Interrupted. This is an intentional cancellation path, not corruption or a bug.
Source
Thrown at core/src/ops/files/copy/strategy.rs:903
let mut last_progress_update = std::time::Instant::now();
let mut source_hasher = if verify_checksum {
Some(blake3::Hasher::new())
} else {
None
};
let mut dest_hasher = if verify_checksum {
Some(blake3::Hasher::new())
} else {
None
};
loop {
if let Err(_) = ctx.check_interrupt().await {
// Clean up partial file so resume doesn't see corrupted data.
let _ = fs::remove_file(destination).await;
return Err(std::io::Error::new(
std::io::ErrorKind::Interrupted,
"Operation cancelled",
));
}
let bytes_read = source_file.read(&mut buffer).await?;
if bytes_read == 0 {
break;
}
let chunk = &buffer[..bytes_read];
dest_file.write_all(chunk).await?;
total_copied += bytes_read as u64;
if let Some(hasher) = &mut source_hasher {
hasher.update(chunk);
}
if let Some(hasher) = &mut dest_hasher {View on GitHub (pinned to 6dfeccf211)
Solutions
- Treat ErrorKind::Interrupted as a clean cancel: report 'cancelled' to the user, do not retry automatically
- If the cancel was unintended, inspect job logs for who issued the interrupt (user action vs shutdown)
- Re-run the copy job; the partial destination was already deleted, so the retry starts clean
Example fix
// before: any error is surfaced as a generic failure
let res = copy_with_strategy(...).await;
// after: distinguish intentional cancellation
match copy_with_strategy(...).await {
Err(e) if e.kind() == std::io::ErrorKind::Interrupted => {
report.cancelled(); // user-initiated, not a defect
}
other => other?,
} Defensive patterns
Strategy: try-catch
Type guard
fn is_cancellation(err: &std::io::Error) -> bool {
err.kind() == std::io::ErrorKind::Interrupted
} Try / catch
match copy_result {
Err(e) if e.kind() == std::io::ErrorKind::Interrupted => {
// clean cancel: partial file already removed by the strategy
state.mark_cancelled();
}
Err(e) => return Err(e),
Ok(_) => {}
} Prevention
- Model cancellation as a first-class UI state, distinct from failure
- Do not auto-retry Interrupted errors: that fights the user's intent
- Remember the strategy deletes the partial destination, so retries always start clean
When it happens
Trigger: User cancels a copy job from the UI or CLI while bytes are streaming; the job manager aborts the job (shutdown, parent job failure, timeout policy) between chunk reads; daemon restart interrupts active copy jobs.
Common situations: Cancelling a large transfer partway; system shutdown racing an in-flight copy; a workflow's child copy job cancelled because a sibling step failed.
Related errors
- Source path is not local
- Destination path is not local
- Checksum verification failed
- Destination must have a device slug for cross-device transfe
- Could not resolve destination device slug '{}' to UUID in li
AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16).
Data as JSON: /api/errors/cc9281abec52eaa6.
Report an issue: GitHub.