charmbracelet/crush · error
failed to access file: %w
Error message
failed to access file: %w
What it means
In createNewFile (edit tool, new-file mode), os.Stat returned an error that is neither nil nor os.IsNotExist, meaning file accessibility could not be determined. The tool aborts rather than risk overwriting an existing file it cannot inspect. Expected errors (file exists / not exists) are handled separately.
Source
Thrown at internal/agent/tools/edit.go:115
notifyLSPs(ctx, lspManager, params.FilePath)
text := fmt.Sprintf("<result>\n%s\n</result>\n", response.Content)
text += getDiagnostics(params.FilePath, lspManager)
response.Content = text
return response, nil
},
)
}
func createNewFile(edit editContext, filePath, content string, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
fileInfo, err := os.Stat(filePath)
if err == nil {
if fileInfo.IsDir() {
return fantasy.NewTextErrorResponse(fmt.Sprintf("path is a directory, not a file: %s", filePath)), nil
}
return fantasy.NewTextErrorResponse(fmt.Sprintf("file already exists: %s", filePath)), nil
} else if !os.IsNotExist(err) {
return fantasy.ToolResponse{}, fmt.Errorf("failed to access file: %w", err)
}
dir := filepath.Dir(filePath)
if err = os.MkdirAll(dir, 0o755); err != nil {
return fantasy.ToolResponse{}, fmt.Errorf("failed to create parent directories: %w", err)
}
sessionID := GetSessionFromContext(edit.ctx)
if sessionID == "" {
return fantasy.ToolResponse{}, fmt.Errorf("session ID is required for creating a new file")
}
_, additions, removals := diff.GenerateDiff(
"",
content,
strings.TrimPrefix(filePath, edit.workingDir),
)
p, err := edit.permissions.Request(View on GitHub (pinned to 7944b8e522)
Solutions
- Check the wrapped error code (EACCES, ELOOP, ENAMETOOLONG) and fix the path accordingly
- Ensure all parent directories are traversable (r+x) by the running process
- Remove or repair symlink cycles in the path
- Shorten the path if NAME_MAX/PATH_MAX is exceeded
Example fix
// before path: /root/secret/newfile.go (running as unprivileged user) // after path: /home/user/project/newfile.go
Defensive patterns
Strategy: validation
Validate before calling
parent := filepath.Dir(target)
for p := parent; p != "/"; p = filepath.Dir(p) {
fi, err := os.Stat(p)
if err != nil {
if os.IsNotExist(err) { continue } // will be created
return fmt.Errorf("cannot inspect %s: %v", p, err)
}
if !fi.IsDir() { return fmt.Errorf("%s is not a directory", p) }
} Try / catch
_, err := os.Stat(filePath)
if err != nil && !os.IsNotExist(err) {
return fmt.Errorf("cannot determine if %s exists: %w", filePath, err)
} // proceed only when err == nil (exists → reject) or os.IsNotExist(err) Prevention
- Target paths inside directories you can read and traverse
- Avoid deeply nested or symlink-heavy paths
- Shorten paths that approach NAME_MAX/PATH_MAX limits
- On network filesystems, tolerate transient stat errors with a retry
When it happens
Trigger: os.Stat fails with EACCES/EACCES on a parent directory (permission denied while traversing the path), ELOOP from a symlink cycle, ENAMETOOLONG, or I/O errors on the filesystem — anything other than ErrNotExist.
Common situations: Creating a file inside a directory the process cannot read/execute; broken symlink loops in the path; very long paths; network filesystems returning transient stat errors.
Related errors
- failed to create parent directories: %w
- failed to access file: %w
- error accessing file: %w
- failed to create parent directories: %w
- failed to create output file: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/b3242362c9c20f0d.
Report an issue: GitHub.