charmbracelet/crush · error
error resolving working directory: %w
Error message
error resolving working directory: %w
What it means
filepath.Abs(workingDir) failed while resolving the view tool's working directory to an absolute path. filepath.Abs rarely fails (it uses os.Getwd when the path is relative), so this usually means the current working directory is unavailable — e.g. the process's cwd was deleted.
Source
Thrown at internal/agent/tools/view.go:118
viewDescription(),
func(ctx context.Context, params ViewParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
if params.FilePath == "" {
return fantasy.NewTextErrorResponse("file_path is required"), nil
}
// Handle builtin skill files (crush: prefix).
if strings.HasPrefix(params.FilePath, skills.BuiltinPrefix) {
resp, err := readBuiltinFile(params, skillTracker)
return resp, err
}
// Handle relative paths
filePath := filepathext.SmartJoin(workingDir, params.FilePath)
// Check if file is outside working directory and request permission if needed
absWorkingDir, err := filepath.Abs(workingDir)
if err != nil {
return fantasy.ToolResponse{}, fmt.Errorf("error resolving working directory: %w", err)
}
absFilePath, err := filepath.Abs(filePath)
if err != nil {
return fantasy.ToolResponse{}, fmt.Errorf("error resolving file path: %w", err)
}
relPath, err := filepath.Rel(absWorkingDir, absFilePath)
isOutsideWorkDir := err != nil || strings.HasPrefix(relPath, "..")
isSkillFile := isInSkillsPath(absFilePath, skillsPaths)
sessionID := GetSessionFromContext(ctx)
if sessionID == "" {
return fantasy.ToolResponse{}, fmt.Errorf("session ID is required for accessing files outside working directory")
}
// Request permission for files outside working directory, unless it's a skill file.
if isOutsideWorkDir && !isSkillFile {View on GitHub (pinned to 7944b8e522)
Solutions
- Pass an absolute path as workingDir to NewViewTool so os.Getwd is never needed
- Ensure the process's original cwd still exists for the process lifetime
- Restart the process from a valid directory
- Recreate the deleted directory
Example fix
// before
NewViewTool(lsp, perms, ft, st, "./", skillPaths...) // relies on os.Getwd
// after
abs, _ := filepath.Abs("./") // resolve once at startup, while cwd is valid
NewViewTool(lsp, perms, ft, st, abs, skillPaths...) Defensive patterns
Strategy: validation
Validate before calling
if !filepath.IsAbs(workingDir) {
if _, err := os.Getwd(); err != nil {
return fmt.Errorf("cannot resolve relative workingDir: %w", err)
}
} Type guard
func isUsableDir(dir string) bool {
abs, err := filepath.Abs(dir)
return err == nil && func() bool { st, err := os.Stat(abs); return err == nil && st.IsDir() }()
} Try / catch
var pe *fs.PathError
if errors.As(err, &pe) {
// cwd deleted: recreate it or restart process from a valid directory
} Prevention
- Always pass an absolute workingDir to NewViewTool
- Avoid deleting a process's cwd while it runs (watch tmpdir cleanup tools)
- Start the process from a stable directory
When it happens
Trigger: The tool was constructed with a relative workingDir and the process's current working directory no longer exists or cannot be stat'd, making os.Getwd inside filepath.Abs fail.
Common situations: Working directory removed while the process runs (deleted tmpdir, unmounted volume); launching the process from a since-deleted directory; race with external tooling cleaning up directories.
Related errors
- error resolving file path: %w
- failed to write file: %w
- failed to read file: %w
- failed to write file: %w
- error checking file: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/0fa2f29fa8910746.
Report an issue: GitHub.