{"record":{"id":"f9c7a4dab6114173","repo":"denoland/deno","slug":"failed-to-copy-to","errorCode":null,"errorMessage":"failed to copy '{}' to '{}': {:?}","messagePattern":"failed to copy '(.+?)' to '(.+?)': (.+?)","errorType":"exception","errorClass":"FsError","httpStatus":null,"severity":"error","filePath":"ext/fs/std_fs.rs","lineNumber":780,"sourceCode":"      // continue copying all entries instead of aborting.\n      if let Err(err) = builder.create(to)\n        && err.kind() != ErrorKind::AlreadyExists\n      {\n        return Err(FsError::Io(err));\n      }\n\n      let mut entries: Vec<_> = fs::read_dir(from)?\n        .map(|res| res.map(|e| e.file_name()))\n        .collect::<Result<_, _>>()?;\n\n      entries.shrink_to_fit();\n      entries\n        .into_par_iter()\n        .map(|file_name| {\n          let from_path = from.join(&file_name);\n          let to_path = to.join(&file_name);\n          let meta = fs::symlink_metadata(&from_path).map_err(|err| {\n            io::Error::new(\n              err.kind(),\n              format!(\n                \"failed to copy '{}' to '{}': {:?}\",\n                from_path.display(),\n                to_path.display(),\n                err,\n              ),\n            )\n          })?;\n          cp_(meta, &from_path, &to_path).map_err(|err| {\n            io::Error::new(\n              err.kind(),\n              format!(\n                \"failed to copy '{}' to '{}': {:?}\",\n                from_path.display(),\n                to_path.display(),\n                err,\n              ),","sourceCodeStart":762,"sourceCodeEnd":798,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/fs/std_fs.rs#L762-L798","documentation":"When Deno.copy()/copySync() copies a directory recursively, each entry is lstat'ed with fs::symlink_metadata before dispatch. If that stat fails, the original error is re-thrown with the same ErrorKind but a formatted message \"failed to copy '<from>' to '<to>': <original error>\" so the failing entry is identifiable (ext/fs/std_fs.rs:780).","triggerScenarios":"Recursive Deno.copy(fromDir, toDir) where an entry disappears between read_dir and lstat (another process pruning build output), EACCES because a subdirectory lost search permission, ENAMETOOLONG on very deep names, or an NFS stale file handle during the walk.","commonSituations":"Copying live build output or log directories while another process writes to them; running without read/search permission on part of the tree; network filesystems with flaky attribute replies.","solutions":["Verify read access before copying: Deno.permissions.querySync({ name: 'read', path: fromDir })","Copy from a stabilized snapshot (stop writers, or tar first) when the tree is mutating","Copy entries individually and skip entries that vanish mid-copy (NotFound race)","Retry the copy once — transient races usually clear"],"exampleFix":"// before\nawait Deno.copy(srcDir, dstDir); // one vanished entry fails the whole copy\n\n// after\nawait Deno.mkdir(dstDir, { recursive: true });\nfor (const entry of Deno.readDirSync(srcDir)) {\n  try {\n    await Deno.copy(`${srcDir}/${entry.name}`, `${dstDir}/${entry.name}`);\n  } catch (e) {\n    if (e instanceof Deno.errors.NotFound) continue; // vanished mid-copy\n    throw e;\n  }\n}","handlingStrategy":"try-catch","validationCode":"async function canReadTree(path: string): Promise<boolean> {\n  const q = await Deno.permissions.query({ name: 'read', path });\n  if (q.state !== 'granted') return false;\n  try {\n    for (const _ of Deno.readDirSync(path)) break; // probe read+search access\n    return true;\n  } catch {\n    return false;\n  }\n}","typeGuard":null,"tryCatchPattern":"for (const entry of Deno.readDirSync(srcDir)) {\n  try {\n    await Deno.copy(`${srcDir}/${entry.name}`, `${dstDir}/${entry.name}`);\n  } catch (e) {\n    if (e instanceof Deno.errors.NotFound) continue; // entry vanished mid-copy\n    if (e instanceof Deno.errors.PermissionDenied) {\n      console.warn(`skipping unreadable entry: ${entry.name}`);\n      continue;\n    }\n    throw e;\n  }\n}","preventionTips":["Copy volatile directories entry-by-entry instead of one recursive call so races only skip entries","Check read permission on the whole tree before starting","Prefer copying a stabilized snapshot of live build/log output"],"tags":["filesystem","copy","directory","race-condition","stat"],"backgroundTag":"file-copy-failed","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}