hasura/graphql-engine · error
failed to copy directory tree as a fallback: %w
Error message
failed to copy directory tree as a fallback: %w
What it means
When os.Rename fails with a cross-device error (EXDEV, errno 18), renameOrCopy falls back to copyTree to copy the directory tree from source to destination; copyTree itself failed. So the move spans filesystems (e.g. /tmp tmpfs → home dir) and the recursive copy hit an error such as ENOSPC, EACCES, or an unreadable source file.
Source
Thrown at cli/plugins/move.go:270
if err != nil && !stderrors.Is(err, fs.ErrNotExist) {
return errors.E(op, fmt.Errorf("error checking move target dir %q: %w", to, err))
}
if fi != nil && fi.IsDir() {
err := os.RemoveAll(to)
if err != nil {
return errors.E(op, fmt.Errorf("error cleaning up dir %q: %w", to, err))
}
}
err = os.Rename(from, to)
// Fallback for invalid cross-device link (errno:18).
if isCrossDeviceRenameErr(err) {
copyErr := copyTree(from, to)
if copyErr != nil {
return errors.E(
op,
fmt.Errorf("failed to copy directory tree as a fallback: %w", copyErr),
)
}
return nil
}
if err != nil {
return errors.E(op, err)
}
return nil
}
// copyTree copies files or directories, recursively.
func copyTree(from, to string) (err error) {
var op errors.Op = "plugins.copyTree"
err = filepath.Walk(from, func(path string, info os.FileInfo, err error) error {View on GitHub (pinned to 724551b9ae)
Solutions
- Free space on the destination filesystem or raise the quota
- Set TMPDIR to a location on the same filesystem as the plugins install dir to avoid the copy entirely
- Verify read permission on all files in the temp staging dir (check the archive extraction)
- Retry the install after making room / fixing perms
Example fix
# before: EXDEV copy from tmpfs fails on big plugin # after TMPDIR=$HOME/tmp hasura plugins install my-plugin
Defensive patterns
Strategy: fallback
Validate before calling
var stat unix.Statfs_t
if err := unix.Statfs(filepath.Dir(installDir), &stat); err == nil && stat.Bavail*uint64(stat.Bsize) < neededBytes {
return errors.New("insufficient space for copy fallback")
} Try / catch
if err := installPlugin(p); err != nil && strings.Contains(err.Error(), "copy directory tree as a fallback") {
// free space on dest, or set TMPDIR to same device, then retry
} Prevention
- Place TMPDIR on the same filesystem as the install dir
- Keep at least archive-size free space before installs
- Check extracted file permissions are readable by the running user
When it happens
Trigger: Staged temp dir and install dir on different devices, and copyTree fails partway: destination disk full, permission mismatch when recreating file modes, or a source file that cannot be read.
Common situations: Small tmpfs /tmp exhausting space while copying a large plugin binary; restrictive umask/permissions on extracted files; NFS/home quotas exceeded.
Related errors
- could not rename/copy directory %q to %q: %w
- writing metadata to file: %w
- reading metadata file: %w
- error finding absolute path for project directory: %w
- did not find required directory. use 'init'?: %w
AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28).
Data as JSON: /api/errors/d9ff118bfd7e9e4c.
Report an issue: GitHub.