plandex-ai/plandex · error
no convo message for ID: %s
Error message
no convo message for ID: %s
What it means
Thrown when a description's ConvoMessageId is set but no message with that ID was found among the loaded conversation messages (convoMessagesById lookup returns nil). It means the description points at a message that does not exist in the plan's convo.
Source
Thrown at app/server/types/active_plan_pending_builds.go:49
}
convoMessagesById := map[string]*db.ConvoMessage{}
for _, msg := range convoMessages {
convoMessagesById[msg.Id] = msg
}
activeBuildsByPath := map[string][]*ActiveBuild{}
for _, desc := range planDescs {
if (!desc.DidBuild && len(desc.Operations) > 0) || len(desc.BuildPathsInvalidated) > 0 {
if desc.ConvoMessageId == "" {
log.Printf("No convo message ID for description: %v\n", desc)
return nil, fmt.Errorf("no convo message ID for description: %v", desc)
}
if convoMessagesById[desc.ConvoMessageId] == nil {
log.Printf("No convo message for ID: %s\n", desc.ConvoMessageId)
return nil, fmt.Errorf("no convo message for ID: %s", desc.ConvoMessageId)
}
// convoMessage := convoMessagesById[desc.ConvoMessageId]
// replyParser := NewReplyParser()
// replyParser.AddChunk(convoMessage.Message, false)
// parserRes := replyParser.FinishAndRead()
numAdded := 0
for _, op := range desc.Operations {
if desc.DidBuild && !desc.BuildPathsInvalidated[op.Path] {
continue
}
if activeBuildsByPath[op.Path] == nil {
activeBuildsByPath[op.Path] = []*ActiveBuild{}
}View on GitHub (pinned to e2d772072e)
Solutions
- Look up the logged ConvoMessageId in the convo_messages table to confirm whether the row was deleted.
- Restore the missing convo message or delete the orphaned description record.
- If supplying convoMessagesArg, ensure it contains ALL messages for the plan (e.g. the full result of db.GetPlanConvo).
- Re-run any migration/backfill that links descriptions to their source messages.
Example fix
// before
builds, err := plan.PendingBuildsByPath(orgId, userId, partialConvo)
// after
fullConvo, err := db.GetPlanConvo(orgId, plan.Id) // pass the complete set
if err != nil { return err }
builds, err := plan.PendingBuildsByPath(orgId, userId, fullConvo) Defensive patterns
Strategy: validation
Validate before calling
msgIds := map[string]bool{}
for _, m := range convo { msgIds[m.Id] = true }
for _, desc := range descs {
if desc.ConvoMessageId != "" && !msgIds[desc.ConvoMessageId] {
return fmt.Errorf("description %s references missing convo message %s", desc.Id, desc.ConvoMessageId)
}
} Type guard
func convoMessageExists(id string, byId map[string]*db.ConvoMessage) bool {
return id != "" && byId[id] != nil
} Try / catch
builds, err := plan.PendingBuildsByPath(orgId, userId, fullConvo)
if err != nil {
if strings.Contains(err.Error(), "no convo message for ID") {
log.Printf("dangling description reference; resync descriptions with convo")
return resyncDescriptions(plan.Id)
}
return err
} Prevention
- Cascade-delete descriptions when their convo messages are removed (FK with ON DELETE CASCADE).
- Never pass partial convo slices as convoMessagesArg; pass the full GetPlanConvo result.
- Validate referential integrity between descriptions and convo messages after migrations.
- Detect and prune orphaned descriptions in a periodic integrity job.
When it happens
Trigger: db.GetConvoMessageDescriptions returns a description whose convo_message_id has no matching row in the convo messages table; passing a partial convoMessagesArg that omits the referenced message; messages deleted after descriptions were created.
Common situations: Orphaned description rows after convo message deletion or plan truncation; cross-plan data corruption from a bad migration; caller passing a filtered/partial convo message slice to PendingBuildsByPath.
Related errors
- no convo message ID for description: %v
- Stream has no branch
- Stream has no plan
- connection to plan stream timed out due to missing heartbeat
- error loading accounts: %v
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/2fa90b554a7a5cbc.
Report an issue: GitHub.