hasura/graphql-engine · error
could not rename/copy directory %q to %q: %w
Error message
could not rename/copy directory %q to %q: %w
What it means
The final atomic-ish step of moveToInstallDir — renameOrCopy(tmp, installDir) moving the staged temp directory into the plugin's install directory — failed. The wrapped error comes from renameOrCopy: target stat/cleanup problems, os.Rename failure, or a failed cross-device copyTree fallback.
Source
Thrown at cli/plugins/move.go:239
tmp, err := os.MkdirTemp("", "hasura-temp-move")
if err != nil {
return errors.E(op, fmt.Errorf("failed to find a temporary director: %w", err))
}
defer os.RemoveAll(tmp)
if err = moveAllFiles(srcDir, tmp, fos); err != nil {
return errors.E(op, fmt.Errorf("failed to move files: %w", err))
}
if err = renameOrCopy(tmp, installDir); err != nil {
defer func() {
os.Remove(installDir)
}()
return errors.E(
op,
fmt.Errorf("could not rename/copy directory %q to %q: %w", tmp, installDir, err),
)
}
return nil
}
// renameOrCopy will try to rename a dir or file. If rename is not supported, a manual copy will be performed.
// Existing files at "to" will be deleted.
func renameOrCopy(from, to string) error {
var op errors.Op = "plugins.renameOrCopy"
fi, err := os.Stat(to)
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)View on GitHub (pinned to 724551b9ae)
Solutions
- Check the wrapped error for the OS cause (permission, ENOSPC, EXDEV fallback failure)
- Remove/clean the existing install dir for the plugin and any stale artifacts, then retry
- Free disk space or set TMPDIR to a filesystem with room (ideally same device as the install dir)
- Fix ownership of the plugins install tree so the current user can replace it
Example fix
# before: tmpfs /tmp too small for copy fallback # after TMPDIR=$HOME/tmp hasura plugins install my-plugin
Defensive patterns
Strategy: fallback
Validate before calling
if fi, err := os.Stat(installDir); err == nil && fi.IsDir() {
if err := os.RemoveAll(installDir); err != nil { return fmt.Errorf("cannot clear old install: %w", err) }
} Try / catch
if err := installPlugin(p); err != nil && strings.Contains(err.Error(), "could not rename/copy directory") {
// clear installDir, ensure same-device TMPDIR with space, retry
} Prevention
- Set TMPDIR to the same filesystem as the plugins dir to avoid EXDEV copies
- Clean old install dirs before upgrade
- Ensure the current user owns the install tree
When it happens
Trigger: Staging succeeded but the tmp→installDir rename failed: installDir exists and cannot be removed (permissions), a cross-device move (/tmp vs home) where copyTree also hit an error, or ENOSPC during the copy.
Common situations: /tmp on tmpfs while the plugins dir is on disk, and the copy runs out of space; leftover root-owned install dir from a previous sudo install; Windows file locking on the target.
Related errors
- could not rename/copy file from %q to %q: %w
- failed to copy directory tree as a fallback: %w
- rename exe to old: %w
- writing metadata to file: %w
- reading metadata file: %w
AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28).
Data as JSON: /api/errors/1f22febe64b2fada.
Report an issue: GitHub.