plandex-ai/plandex · error
error storing user message: %v
Error message
error storing user message: %v
What it means
This error is produced by the storeUserMessage goroutine's recover handler: the goroutine that persists the user's prompt message panicked. The panic value is wrapped and sent on innerErrCh so loadTellPlan aborts instead of crashing the process.
Source
Thrown at app/server/model/plan/tell_load.go:198
res, err := db.GetPlanConvo(currentOrgId, planId)
if err != nil {
log.Printf("Error getting plan convo: %v\n", err)
errCh <- fmt.Errorf("error getting plan convo: %v", err)
return
}
convo = res
UpdateActivePlan(planId, branch, func(ap *types.ActivePlan) {
ap.MessageNum = len(convo)
})
promptTokens := shared.GetNumTokensEstimate(req.Prompt)
innerErrCh := make(chan error, 2)
go func() {
defer func() {
if r := recover(); r != nil {
log.Printf("panic in storeUserMessage: %v\n%s", r, debug.Stack())
innerErrCh <- fmt.Errorf("error storing user message: %v", r)
runtime.Goexit() // don't allow outer function to continue and double-send to channel
}
}()
if iteration == 0 && missingFileResponse == "" && !req.IsUserContinue {
num := len(convo) + 1
log.Printf("[TellLoad] storing user message | len(convo): %d | num: %d\n", len(convo), num)
promptMsg = &db.ConvoMessage{
OrgId: currentOrgId,
PlanId: planId,
UserId: currentUserId,
Role: openai.ChatMessageRoleUser,
Tokens: promptTokens,
Num: num,
Message: req.Prompt,
Flags: shared.ConvoMessageFlags{View on GitHub (pinned to e2d772072e)
Solutions
- Inspect the 'panic in storeUserMessage' log stack trace to pinpoint the deref site
- Ensure the repo (git repo wrapper) is successfully opened and non-nil before starting the goroutine
- Validate auth.User and currentUserId are set before calling loadTellPlan
- Guard UpdateActivePlan against a missing active plan entry for planId/branch
- Run with -race to detect concurrent access to the active plan or repo
Example fix
// before
_, err = db.StoreConvoMessage(repo, promptMsg, auth.User.Id, branch, true)
// after
if repo == nil || auth == nil || auth.User == nil {
innerErrCh <- fmt.Errorf("error storing user message: nil repo or user")
return
}
_, err = db.StoreConvoMessage(repo, promptMsg, auth.User.Id, branch, true) Defensive patterns
Strategy: validation
Validate before calling
if repo == nil {
return fmt.Errorf("git repo not initialized; cannot store user message")
}
if auth == nil || auth.User == nil || auth.User.Id == "" {
return fmt.Errorf("authenticated user required to store user message")
} Type guard
func canStoreUserMessage(repo *git.Repository, auth *auth.Session) bool {
return repo != nil && auth != nil && auth.User != nil && auth.User.Id != ""
} Try / catch
if err := <-innerErrCh; err != nil && strings.HasPrefix(err.Error(), "error storing user message:") {
// recovered panic path — inspect stack trace already logged, abort plan load
return err
} Prevention
- Ensure the git repo wrapper is opened and kept alive for the request lifetime
- Check active plan exists for planId/branch before UpdateActivePlan mutations
- Validate session/user context before Tell entry point
- Enable -race in CI to catch concurrent repo/plan access
When it happens
Trigger: A panic inside the goroutine guarded at tell_load.go:198 — e.g., nil repo pointer, nil promptMsg construction failure, nil map access while building the db.ConvoMessage, or a panic inside db.StoreConvoMessage or UpdateActivePlan during the first iteration (iteration==0, no missingFileResponse, not IsUserContinue).
Common situations: Git repo wrapper (repo) is nil because the repository failed to load or was closed concurrently; active plan record was deleted mid-request causing nil deref in UpdateActivePlan; nil auth.User or currentUserId from a stale session.
Related errors
- error getting plan convo: %v
- error getting plan summaries: %v
- error getting org user config: %v
- error getting plan subtasks: %v %s
- panic in UpdateContexts: %v\n%s
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/f9047c5a39eb90db.
Report an issue: GitHub.