charmbracelet/crush · error
failed to create parent directories: %w
Error message
failed to create parent directories: %w
What it means
After verifying the target doesn't exist, createNewFile runs os.MkdirAll on the file's parent directory and wraps any failure. The wrapped error contains the OS reason: a path component exists as a file, the directory isn't writable, or the filesystem is read-only.
Source
Thrown at internal/agent/tools/edit.go:120
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(
edit.ctx,
permission.CreatePermissionRequest{
SessionID: sessionID,
Path: fsext.PathOrPrefix(filePath, edit.workingDir),
ToolCallID: call.ID,View on GitHub (pinned to 7944b8e522)
Solutions
- Inspect the wrapped error; if EEXIST, the parent name collides with an existing file — pick a different path
- Check directory write permissions (ls -ld)
- Confirm the filesystem is writable (mount options)
- Create the directory manually first if permissions need adjustment
Example fix
// before file_path: "README.md/new.go" // README.md is a file // after file_path: "internal/new.go"
Defensive patterns
Strategy: validation
Validate before calling
parent := filepath.Dir(target)
if fi, err := os.Stat(parent); err == nil && !fi.IsDir() {
return fmt.Errorf("%s already exists and is not a directory", parent)
}
if f, err := os.OpenFile(parent, os.O_RDONLY, 0); err != nil {
return fmt.Errorf("parent %s not usable: %v", parent, err)
} else { f.Close() } Try / catch
if err := os.MkdirAll(dir, 0o755); err != nil {
if errors.Is(err, fs.ErrExist) {
return fmt.Errorf("path component %s is a file, not a directory", dir)
}
return err
} Prevention
- Don't build file paths whose parent names collide with existing files
- Create new files inside the writable working directory tree
- Check mount options (read-only) before scaffolding in containers
- Fix directory permissions before retrying the create
When it happens
Trigger: Parent directory of the new file cannot be created: e.g. creating 'src/newfile.go' when 'src' is an existing file; write-protected parent; read-only mount; ENOSPC.
Common situations: LLM chose a file_path whose parent collides with an existing file; scaffolding into vendor/ or read-only directories; container filesystem read-only; path contains a symlink to a non-directory.
Related errors
- failed to create parent directories: %w
- failed to access file: %w
- failed to access file: %w
- error creating directory: %w
- failed to create data directory: %q %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/e1a10b4cdafa9102.
Report an issue: GitHub.