neondatabase/neon · error
Received failure response for copy from {from} to {to}.
Error message
Received failure response for copy from {from} to {to}. What it means
CopyStatus::Failed from Azure's async Copy Blob: the copy was attempted but the service could not read from the source. Typical causes: no read permission on the source (SAS missing read scope), the source was deleted before the copy service read it, or the source blob is in the Archive access tier (archived blobs cannot be copied without rehydration).
Source
Thrown at libs/remote_storage/src/azure_blob.rs:906
let source_url = format!(
"{}/{}",
self.client.url()?,
self.relative_path_to_name(from)
);
let builder = blob_client.copy(Url::from_str(&source_url)?);
let copy = builder.into_future();
let result = copy.await?;
copy_status = Some(result.copy_status);
loop {
match copy_status.as_ref().expect("we always set it to Some") {
CopyStatus::Aborted => {
anyhow::bail!("Received abort for copy from {from} to {to}.");
}
CopyStatus::Failed => {
anyhow::bail!("Received failure response for copy from {from} to {to}.");
}
CopyStatus::Success => return Ok(()),
CopyStatus::Pending => (),
}
// The copy is taking longer. Waiting a second and then re-trying.
// TODO estimate time based on copy_progress and adjust time based on that
tokio::time::sleep(Duration::from_millis(1000)).await;
let properties = blob_client.get_properties().into_future().await?;
let Some(status) = properties.blob.properties.copy_status else {
tracing::warn!("copy_status for copy is None!, from={from}, to={to}");
return Ok(());
};
copy_status = Some(status);
}
};
let res = tokio::select! {
res = op => res,View on GitHub (pinned to 8f60b04da4)
Solutions
- Verify read access on the source: the SAS/identity needs read on the source container or blob, not just write on the destination
- Check the source still exists and is not in Archive tier — rehydrate it or copy from a Hot/Cool replica
- If the source is gone, propagate failure upstream instead of retrying
- For cross-account copies use a source URL that embeds a read-scoped SAS token
Example fix
// before: copy with a bare source URL (requires read on source, fails cross-account)
let builder = blob_client.copy(Url::from_str(&source_url)?);
// after: copy from a source URL carrying a read-scoped SAS
let source_url = format!("{}/{}?{}", src_account_url, src_blob_name, src_read_sas);
let builder = blob_client.copy(Url::from_str(&source_url)?); Defensive patterns
Strategy: try-catch
Validate before calling
// Verify the source is readable (and not archived) before issuing the server-side copy.
async fn source_copyable(storage: &GenericRemoteStorage, from: &RemotePath, cancel: &CancellationToken) -> anyhow::Result<()> {
match storage.head_object(from.get_path().to_string(), cancel).await {
Ok(meta) => {
// rejections for archived sources are reported as access errors downstream
let _ = meta;
Ok(())
}
Err(DownloadError::NotFound) => anyhow::bail!("source vanished before copy"),
Err(e) => Err(e.into()),
}
} Try / catch
// Failure is often permanent (permissions/archive): inspect before retrying.
match storage.copy(&from, &to, &cancel).await {
Ok(()) => Ok(()),
Err(e) => {
let msg = format!("{e:#}");
if msg.contains("Received failure response for copy") {
// check source access + tier, fix, then a single retry — do not blind-retry
verify_source_access(&from).await?;
storage.copy(&from, &to, &cancel).await
} else {
Err(e)
}
}
} Prevention
- Grant read scope on the source in addition to write on the destination (SAS/identity)
- Exclude Archive-tier blobs from copy pipelines or rehydrate them first
- Delete-proof sources (defer GC) while copies reference them
When it happens
Trigger: Copying a source the credentials cannot read (cross-account or cross-container copy without a read-scoped source SAS); source deleted between the copy request and the server reading it; source blob in Archive tier; source lease/retention states preventing reads.
Common situations: Lifecycle policies moving blobs to Archive tier; copying across storage accounts with insufficient SAS scopes; GC deleting source objects concurrently with copy operations.
Related errors
- Received abort for copy from {from} to {to}.
- Failed to upload all blocks {:#?}
- Received ListVersions response for key={key} with version_id
- Failed to send signal to {process_name} with pid {pid}: {e}
- Failed to send signal to process with pid {pid}: {err}
AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16).
Data as JSON: /api/errors/c046dcf4c17e0059.
Report an issue: GitHub.