googleapis/mcp-toolbox · error
failed to stat file: %w
Error message
failed to stat file: %w
What it means
This error is emitted by the `migrate` command in runMigrate when `os.Stat(filePath)` fails on a file it is about to rewrite. The command needs the file's mode bits (to preserve permissions when rewriting) and the file's existence, so a stat failure aborts processing of that one file and the error is appended to the collected error list while other files continue to be processed. Because it wraps the raw os.Stat error, the underlying cause (e.g. ENOENT, EACCES, ENOTDIR) is always included in the wrapped message.
Source
Thrown at cmd/internal/migrate/command.go:95
continue
}
newBuf, err := internal.ConvertConfig(ctx, buf)
if err != nil {
logger.ErrorContext(ctx, err.Error())
errs = append(errs, err)
continue
}
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)View on GitHub (pinned to 8cc6e09de2)
Solutions
- Verify the path exists with `ls -l <filePath>` and fix any typo in the configured path/glob.
- Check permissions on the file's parent directory (the process needs +x on it); run as a user with access or chown/chmod the path.
- If it is a broken symlink, remove it or recreate it pointing at a real file.
- Re-run migrate; the error is per-file and the command continues with other files, so inspect the full error list and fix each offending path.
- Check that no concurrent process deleted or moved the file during the run.
Example fix
// before: path comes from a possibly stale config
filePath := cfg.OldPath
info, err := os.Stat(filePath) // ENOENT
// after: resolve and validate the path up front
if resolved, err := filepath.EvalSymlinks(cfg.OldPath); err == nil {
filePath = resolved
} else {
log.Fatalf("migrate input %q does not exist: %v", cfg.OldPath, err)
} Defensive patterns
Strategy: validation
Validate before calling
info, err := os.Stat(filePath)
if err != nil {
return fmt.Errorf("skipping %s: not statable (%v); check path and permissions", filePath, err)
}
if info.IsDir() {
return fmt.Errorf("%s is a directory, expected a file", filePath)
} Prevention
- Stat every input path in a dry-run pass before running migrate for real.
- Avoid hardcoding absolute paths; derive them from the repo root at runtime.
- Run migrate as the same user that owns the target files.
- Watch for broken symlinks after branch switches or partial cleanups; use filepath.EvalSymlinks.
When it happens
Trigger: Running the migrate command with a path that does not exist, points to a broken symlink, or lives in a directory the process cannot traverse. Also occurs when the file is deleted between path collection and the stat call, or the path is too long / is a non-directory component (ENOTDIR).
Common situations: Typo in a file path or glob expansion produced no/stale paths; running the toolbox from a container or service account whose user lacks execute permission on the parent directory; a broken symlink left behind after an aborted run; an interrupted previous migrate run removed the file but left the .bak.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- failed to rename file: %w
- failed to write to file: %w
- failed to restore original 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/fedffbebcbb84b4d.
Report an issue: GitHub.