charmbracelet/crush · error
failed to create session for non-interactive mode: %w
Error message
failed to create session for non-interactive mode: %w
What it means
RunNonInteractive resolves the session via app.resolveSession (creating a new session, or continuing an existing one given continueSessionID/useLast); any error is wrapped with this message. Session creation touches the SQLite store, so this usually indicates a database problem rather than an LLM issue.
Source
Thrown at internal/app/app.go:330
}
// Non-interactive runs get a single shot at the tool palette, so wait for
// MCP initialization to settle before reading MCP tools. The coordinator
// waits again for the same reason (it is the gate the client/server path
// goes through); doing it here too surfaces the failure before we create a
// session, and lets the UpdateModels below see every MCP tool.
if err := mcp.WaitForInit(ctx); err != nil {
return fmt.Errorf("failed to wait for MCP initialization: %w", err)
}
// force update of agent models before running so mcp tools are loaded
app.AgentCoordinator.UpdateModels(ctx)
defer stopSpinner()
sess, err := app.resolveSession(ctx, continueSessionID, useLast)
if err != nil {
return fmt.Errorf("failed to create session for non-interactive mode: %w", err)
}
if continueSessionID != "" || useLast {
slog.Info("Continuing session for non-interactive run", "session_id", sess.ID)
// If no explicit model override was requested, restore the
// model/provider from the last assistant message in the
// session, provided it is still available.
if largeModel == "" && smallModel == "" {
if err := app.restoreModelFromSession(ctx, sess.ID); err != nil {
slog.Warn("Failed to restore model from session", "error", err)
}
}
} else {
slog.Info("Created session for non-interactive run", "session_id", sess.ID)
}
// Automatically approve all permission requests for this non-interactive
// session.View on GitHub (pinned to 7944b8e522)
Solutions
- Verify the DB file location is writable (check $TMPDIR/$XDG_CACHE_HOME paths)
- Pass a valid --continue session id (list sessions via `crush sessions`) or omit it to start fresh
- Move/delete the corrupt DB file so migrations run again on a fresh DB
- Upgrade crush if the DB was written by an incompatible version
Example fix
// before crush run --continue abc123-definitely-stale "continue" // after crush sessions // find a valid id crush run --continue 8f2c... "continue"
Defensive patterns
Strategy: validation
Validate before calling
if continueSessionID != "" {
sessions := listSessions() // e.g. via `crush sessions`
if !contains(sessions, continueSessionID) {
return fmt.Errorf("unknown session id: %s", continueSessionID)
}
}
if _, err := os.Stat(dbPath); err != nil || !writable(dbPath) {
return fmt.Errorf("session DB not writable: %s", dbPath)
} Try / catch
if err := app.RunNonInteractive(ctx, w, prompt, "", "", true, contID, useLast); err != nil {
if strings.Contains(err.Error(), "failed to create session") {
// retry once without continue to start a fresh session
return app.RunNonInteractive(ctx, w, prompt, "", "", true, "", false)
}
return err
} Prevention
- Refresh session ids from `crush sessions` instead of hardcoding them
- Keep the crush cache/data directory writable and non-full
- Avoid downgrading crush across DB migrations
When it happens
Trigger: resolveSession fails: the SQLite DB cannot be opened/migrated, the continueSessionID does not exist, or the 'use last session' lookup fails.
Common situations: Read-only or full disk where the crush DB lives; corrupted ~/.cache/crush DB after an abrupt kill; passing a stale --continue session id that was deleted; schema migration failure after a version upgrade.
Related errors
- failed to get session: %w
- error creating file history: %w
- failed to get last assistant message: %w
- failed to resolve session: %w
- failed to list sessions: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/71895b9509f76e7c.
Report an issue: GitHub.