googleapis/mcp-toolbox · error

failed to rename file: %w

Error message

failed to rename file: %w

What it means

Thrown when runMigrate cannot rename the original file to `<filePath>.bak` via `os.Rename` before writing the migrated content. The backup rename is part of a safe write sequence (backup, write, restore on failure); if it fails the file is left untouched and the error (with the wrapped OS reason) is appended to errs and that file is skipped. Typical underlying errors are EACCES/EPERM (no write permission on the directory) or EXDEV (source and destination on different filesystems, which cannot happen here since only `.bak` is appended, so permission/locking issues dominate).

Source

Thrown at cmd/internal/migrate/command.go:103

		if cmp.Equal(buf, newBuf) {
			continue
		}

		if cmd.dryRun {
			logger.DebugContext(ctx, fmt.Sprintf("printing migration to output for file: %s", filePath))
			fmt.Fprintln(opts.IOStreams.Out, string(newBuf))
		} else {
			info, err := os.Stat(filePath)
			if err != nil {
				errMsg := fmt.Errorf("failed to stat file: %w", err)
				logger.ErrorContext(ctx, errMsg.Error())
				errs = append(errs, errMsg)
				continue
			}
			backupFile := filePath + ".bak"
			err = os.Rename(filePath, backupFile)
			if err != nil {
				errMsg := fmt.Errorf("failed to rename file: %w", err)
				logger.ErrorContext(ctx, errMsg.Error())
				errs = append(errs, errMsg)
				continue
			}
			logger.DebugContext(ctx, fmt.Sprintf("successfully renamed %s to %s", filePath, backupFile))

			// set the permission to the original file's permission.
			err = os.WriteFile(filePath, newBuf, info.Mode().Perm())
			if err != nil {
				errMsg := fmt.Errorf("failed to write to file: %w", err)
				// restoring original file
				if removeErr := os.Remove(filePath); removeErr != nil { // Attempt to remove the possibly partial file to ensure Rename succeeds.
					errMsg = errors.Join(errMsg, removeErr)
				}
				if restoreErr := os.Rename(backupFile, filePath); restoreErr != nil {
					fullRestoreErr := fmt.Errorf("failed to restore original file: %w", restoreErr)
					errMsg = errors.Join(errMsg, fullRestoreErr)
				}

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Check directory write permission: `ls -ld <dir>`; run migrate as a user with write access or fix ownership with chown/chmod.
  2. Verify the volume is not mounted read-only (`mount | grep <dir>`) and remount read-write.
  3. Look for a stale `filePath.bak` and remove it, then re-run migrate.
  4. Close any process holding locks on the file (editors, antivirus, other containers) and retry.
  5. Ensure the filesystem is not full: `df -h <dir>`.
Defensive patterns

Strategy: validation

Validate before calling

dir := filepath.Dir(filePath)
probe := filepath.Join(dir, ".migrate_probe")
if err := os.WriteFile(probe, nil, 0o600); err != nil {
    return fmt.Errorf("directory %s is not writable: %v", dir, err)
}
os.Remove(probe)

Prevention

When it happens

Trigger: The directory containing the file is not writable by the current user, the file is immutable (chattr +i) or held by another process that blocks rename (rare on Linux, common on Windows file locks), or the filesystem is full/read-only.

Common situations: Running migrate inside a Docker container whose mounted volume is read-only; editing files owned by another user without sudo; a leftover `.bak` from a previous crashed run combined with odd directory ACLs; antivirus or editor locking the file on Windows/macOS; disk mounted read-only after filesystem errors.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/e4dbfbeddd74d172. Report an issue: GitHub.