charmbracelet/crush · error
session ID is required for accessing directories outside wor
Error message
session ID is required for accessing directories outside working directory
What it means
The ls tool allows free directory access inside the configured working directory, but when the resolved path escapes it (filepath.Rel yields a '..'-prefixed path or fails), a permission request tied to a session is required. Without a session ID in the context the tool cannot create that request and fails with this error.
Source
Thrown at internal/agent/tools/ls.go:102
searchPath = filepathext.SmartJoin(workingDir, searchPath)
// Check if directory is outside working directory and request permission if needed
absWorkingDir, err := filepath.Abs(workingDir)
if err != nil {
return fantasy.NewTextErrorResponse(fmt.Sprintf("error resolving working directory: %v", err)), nil
}
absSearchPath, err := filepath.Abs(searchPath)
if err != nil {
return fantasy.NewTextErrorResponse(fmt.Sprintf("error resolving search path: %v", err)), nil
}
relPath, err := filepath.Rel(absWorkingDir, absSearchPath)
if err != nil || strings.HasPrefix(relPath, "..") {
// Directory is outside working directory, request permission
sessionID := GetSessionFromContext(ctx)
if sessionID == "" {
return fantasy.ToolResponse{}, fmt.Errorf("session ID is required for accessing directories outside working directory")
}
granted, err := permissions.Request(
ctx,
permission.CreatePermissionRequest{
SessionID: sessionID,
Path: absSearchPath,
ToolCallID: call.ID,
ToolName: LSToolName,
Action: "list",
Description: fmt.Sprintf("List directory outside working directory: %s", absSearchPath),
Params: LSPermissionsParams(params),
},
)
if err != nil {
return fantasy.ToolResponse{}, err
}
if !granted {View on GitHub (pinned to 7944b8e522)
Solutions
- Keep the search path inside the working directory so the permission path is never taken.
- Run the tool through the agent pipeline so GetSessionFromContext returns a valid session.
- In tests, inject a session ID into the context before calling the tool.
Example fix
// before
ListDirectory("/etc", params) // outside working dir, no session in ctx
// after
ctx = WithSession(ctx, sessionID) // or use a path under WorkingDir() Defensive patterns
Strategy: validation
Validate before calling
abs, _ := filepath.Abs(path)
rel, err := filepath.Rel(workDir, abs)
if err != nil || strings.HasPrefix(rel, "..") {
// ensure session context present before calling
} Type guard
func insideWorkDir(path, workDir string) bool {
rel, err := filepath.Rel(workDir, path)
return err == nil && !strings.HasPrefix(rel, "..")
} Try / catch
if err != nil {
if strings.Contains(err.Error(), "session ID is required") { /* run within a session */ }
} Prevention
- Keep tool paths within the configured working directory
- Inject session IDs when embedding tools in custom flows
- Grant permissions ahead of time via config allow-lists
When it happens
Trigger: Calling the ls tool with a path outside cfg.WorkingDir() while the context has no session ID, e.g. direct tool invocation in tests or scripts.
Common situations: Pointing ls at /etc or a sibling project root from a non-session execution path; running the tool handler in isolation without session plumbing.
Related errors
- session ID is required for executing shell command
- session ID is required for downloading files
- failed to create parent directories: %w
- failed to create output file: %w
- failed to access file: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/f7198d606255594c.
Report an issue: GitHub.