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
The new-file path of MultiEdit requires a session ID so the created file can be linked to file history (files.Create). The session ID is read from the request context; when it is absent the tool refuses to create the file instead of silently losing history. This indicates the tool was invoked outside a proper agent session context.
Source
Thrown at internal/agent/tools/multiedit.go:173
// Check if file already exists
if _, err := os.Stat(params.FilePath); err == nil {
return fantasy.NewTextErrorResponse(fmt.Sprintf("file already exists: %s", params.FilePath)), nil
} else if !os.IsNotExist(err) {
return fantasy.ToolResponse{}, fmt.Errorf("failed to access file: %w", err)
}
// Create parent directories
dir := filepath.Dir(params.FilePath)
if err := os.MkdirAll(dir, 0o755); err != nil {
return fantasy.ToolResponse{}, fmt.Errorf("failed to create parent directories: %w", err)
}
currentContent, failedEdits, whitespaceCorrected := applyEditsToContent(firstEdit.NewString, params.Edits[1:], 1)
// Get session and message IDs
sessionID := GetSessionFromContext(edit.ctx)
if sessionID == "" {
return fantasy.ToolResponse{}, fmt.Errorf("session ID is required for creating a new file")
}
// Check permissions
_, additions, removals := diff.GenerateDiff("", currentContent, strings.TrimPrefix(params.FilePath, edit.workingDir))
editsApplied := len(params.Edits) - len(failedEdits)
var description string
if len(failedEdits) > 0 {
description = fmt.Sprintf("Create file %s with %d of %d edits (%d failed)", params.FilePath, editsApplied, len(params.Edits), len(failedEdits))
} else {
description = fmt.Sprintf("Create file %s with %d edits", params.FilePath, editsApplied)
}
p, err := edit.permissions.Request(edit.ctx, permission.CreatePermissionRequest{
SessionID: sessionID,
Path: fsext.PathOrPrefix(params.FilePath, edit.workingDir),
ToolCallID: call.ID,
ToolName: MultiEditToolName,
Action: "write",View on GitHub (pinned to 7944b8e522)
Solutions
- Ensure the tool executes inside the agent run loop where the session ID is stored in the context
- When invoking tools programmatically, inject the session ID into ctx the same way the coordinator does (see GetSessionFromContext/SetSessionFromContext usage)
- Retry via the normal agent pipeline rather than calling the tool directly
- If hit in tests, set a session ID in the tool context before calling Run
Example fix
// before resp, _ := tool.Run(ctx, params) // ctx has no session // after ctx = session.NewContext(ctx, sessionInfo) // inject session before invoking resp, _ := tool.Run(ctx, params)
Defensive patterns
Strategy: validation
Validate before calling
if GetSessionFromContext(ctx) == "" {
return fmt.Errorf("session ID missing from context")
}
// proceed with tool.Run(ctx, params) Try / catch
if _, err := tool.Run(ctx, params); err != nil {
if strings.Contains(err.Error(), "session ID is required") {
ctx = session.NewContext(ctx, sess)
_, err = tool.Run(ctx, params)
}
} Prevention
- Always invoke tools through the agent/coordinator pipeline
- Keep a single helper that builds tool contexts with session info
- Add a test asserting session presence before tool Run
- Don't rebuild context.Context from scratch when wrapping tool calls
When it happens
Trigger: processMultiEditWithCreation runs with params.FilePath pointing to a non-existent file and GetSessionFromContext(edit.ctx) returns "" — i.e. the tool executed without a session-scoped context (direct/manual tool invocation, lost context values, or a harness that forgot to stash the session ID).
Common situations: Calling the tool from tests or custom code without WithContext session injection; a refactor moved tool construction outside the session scope; MCP or subagent plumbing dropping the session from the context chain.
Related errors
- session id missing from context
- session id missing from context
- session ID is required for downloading files
- session ID is required for creating a new file
- %s
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/3fc6c574eec70b91.
Report an issue: GitHub.