charmbracelet/crush · error
session ID is required for creating a new file
Error message
session ID is required for creating a new file
What it means
Like the download tool, createNewFile requires a session ID from the request context to attach to the permission request and file tracking for the newly created file. An empty session ID is an invariant violation and the tool refuses to create the file.
Source
Thrown at internal/agent/tools/edit.go:125
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,
ToolName: EditToolName,
Action: "write",
Description: fmt.Sprintf("Create file %s", filePath),
Params: EditPermissionsParams{
FilePath: filePath,View on GitHub (pinned to 7944b8e522)
Solutions
- Run file creation through the standard agent path, which injects the session ID
- In tests, add the session ID to the context before invoking the handler
- Audit any code that constructs a fresh context.Context for tool calls and re-attach session values
Example fix
// before resp, _ := editTool.Handle(context.Background(), params, call) // after ctx := WithSessionContext(context.Background(), sessionID) resp, _ := editTool.Handle(ctx, params, call)
Defensive patterns
Strategy: validation
Validate before calling
if GetSessionFromContext(edit.ctx) == "" {
return nil, fmt.Errorf("edit tool requires a session-scoped context")
} Try / catch
resp, err := editTool.Handle(ctx, params, call)
if err != nil && strings.Contains(err.Error(), "session ID is required") {
return fmt.Errorf("wiring bug: re-invoke via the agent so ctx carries the session ID")
} Prevention
- Create files through the standard agent path so the session context is injected
- In tests, replicate the agent's context key setup for sessions
- Never replace the context with context.Background() between agent setup and tool execution
When it happens
Trigger: The edit tool's createNewFile handler runs with a context lacking the session ID key — direct invocation in tests, a custom agent harness not setting the session, or context being replaced between agent setup and tool execution.
Common situations: Tests calling the tool handler directly without the session context; embedding edit in a custom pipeline that rebuilds the context; regressions in agent wiring after refactors.
Related errors
- session ID is required for downloading files
- session ID is required for accessing files outside working d
- session id missing from context
- session id missing from context
- session ID is required for executing shell command
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/c0066f09418e9bcd.
Report an issue: GitHub.