googleapis/mcp-toolbox · critical
failed to restore original file: %w
Error message
failed to restore original file: %w
What it means
This is the secondary error raised when BOTH the write of migrated content failed (error 47) AND the automatic restore (`os.Rename(backupFile, filePath)`) also failed. It is joined with the write error via `errors.Join`, so the reported message contains the original write failure plus 'failed to restore original file'. At this point the original content lives only in `<filePath>.bak` and the target path may be missing or hold a partial file, making this the most dangerous state the migrate command can produce.
Source
Thrown at cmd/internal/migrate/command.go:119
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)
}
logger.ErrorContext(ctx, errMsg.Error())
errs = append(errs, errMsg)
continue
}
logger.DebugContext(ctx, fmt.Sprintf("migration completed for file: %s", filePath))
}
}
logger.InfoContext(ctx, "migration ended!")
// If errs is empty, errors.Join returns nil
return errors.Join(errs...)
}
View on GitHub (pinned to 8cc6e09de2)
Solutions
- Immediately recover manually: `mv <filePath>.bak <filePath>` — the original content is in the .bak.
- If `.bak` is missing, restore the file from version control or backups; never leave a partial file in place.
- Fix the root environmental cause (free disk space, remount read-write, fix permissions) before re-running migrate.
- Avoid concurrent processes touching the same paths during migrate (lock or stop other tooling).
- Re-run migrate and confirm the error list is empty.
Example fix
// before: assuming .bak always exists
// after: verify and restore defensively before re-running
if _, err := os.Stat("config.yaml.bak"); err == nil {
if err := os.Rename("config.yaml.bak", "config.yaml"); err != nil {
log.Fatalf("manual restore failed: %v", err)
}
} Defensive patterns
Strategy: fallback
Validate before calling
before, err := os.ReadFile(filePath)
if err != nil { return err }
if err := os.WriteFile(filePath+".pre-migrate-copy", before, 0o600); err != nil {
return fmt.Errorf("cannot create safety copy: %v", err)
} Try / catch
defer func() {
if r := recover(); r != nil || failed {
if _, err := os.Stat(path + ".bak"); err == nil {
_ = os.Remove(path) // drop partial file
if rErr := os.Rename(path+".bak", path); rErr != nil {
log.Fatalf("CRITICAL: could not restore %s from .bak: %v", path, rErr)
}
}
}
}() Prevention
- Make an explicit copy of the file before any migrate run on important paths.
- Never delete `file.bak` until the migrated file has been verified (build/test passes).
- Keep migrate targets on a healthy local filesystem; avoid NFS and read-only mounts.
- Do not run migrate concurrently with other tooling touching the same files.
- If you see the joined restore error, treat data as at-risk and restore from VCS/backup first.
When it happens
Trigger: After a failed os.WriteFile, the cleanup os.Remove(filePath) or the restore os.Rename(backupFile, filePath) fails — e.g. the directory became non-writable, the .bak was concurrently deleted, or the .bak itself sits on a failing filesystem. Any condition causing the initial failure usually also causes the restore to fail.
Common situations: Disk full: both write and restore fail; the file is left missing with only `file.bak` present. Container volume switched to read-only mid-run. Another process (or a previous crashed run) already removed the .bak. NFS stale-handle errors after the server restarted.
Related errors
- failed to stat file: %w
- failed to rename file: %w
- failed to write to file: %w
- error finding YAML files in %q: %w
- error finding YML files in %q: %w
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/5be13388dc0223c3.
Report an issue: GitHub.