{"record":{"id":"cbdf732a91197514","repo":"plandex-ai/plandex","slug":"error-adding-convo-tokens-v","errorCode":null,"errorMessage":"error adding convo tokens: %v","messagePattern":"error adding convo tokens: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/server/db/convo_helpers.go","lineNumber":134,"sourceCode":"\t\treturn \"\", fmt.Errorf(\"error marshalling convo message: %v\", err)\n\t}\n\n\terr = os.MkdirAll(convoDir, os.ModePerm)\n\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"error creating convo dir: %v\", err)\n\t}\n\n\terr = os.WriteFile(filepath.Join(convoDir, message.Id+\".json\"), bytes, os.ModePerm)\n\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"error writing convo message: %v\", err)\n\t}\n\n\terr = AddPlanConvoMessage(message, branch)\n\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"error adding convo tokens: %v\", err)\n\t}\n\n\tvar desc string\n\tif message.Role == openai.ChatMessageRoleUser {\n\t\tdesc = \"💬 User prompt\"\n\t\t// TODO: add user name\n\t} else {\n\t\tdesc = \"🤖 Plandex reply\"\n\t\tif message.Stopped {\n\t\t\tdesc += \" | 🛑 \" + color.New(color.FgHiRed).Sprint(\"stopped\")\n\t\t}\n\t}\n\n\treplyTags := message.Flags.GetReplyTags()\n\n\tvar msg string\n\tif len(replyTags) > 0 {\n\t\tmsg = fmt.Sprintf(\"Message #%d | %s | %s | %d 🪙\", message.Num, desc, strings.Join(replyTags, \" | \"), message.Tokens)","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/db/convo_helpers.go#L116-L152","documentation":"This error wraps any failure returned by AddPlanConvoMessage, which stores the per-conversation token accounting after a convo message is persisted. StoreConvoMessage has already written the message row itself, so the message content exists but the token counters are stale. The %v verb interpolates the underlying cause (SQL error, constraint violation, connection issue).","triggerScenarios":"Calling StoreConvoMessage (directly or via StorePartialReply/storeAssistantReply) when AddPlanConvoMessage fails: invalid branch reference, DB connection drop, schema mismatch in the plan convo tokens table, or a nil message/branch argument producing invalid SQL parameters.","commonSituations":"Streaming a partial reply whose branch was deleted concurrently; migrations out of date so token columns are missing; database connectivity blips mid-request; passing a branch name that doesn't exist after a git/plan branch switch.","solutions":["Inspect the wrapped %v cause in the log to identify the underlying SQL error","Run database migrations (MigrationsUp) to ensure token tables/columns exist","Verify the branch parameter matches an existing plan branch before storing the message","Check DB connectivity and retry StoreConvoMessage; note the message row was already written so avoid duplicating it"],"exampleFix":"// before\nmsg, err := db.StoreConvoMessage(ctx, msg, branch, true)\n// after\nif _, err := db.GetBranch(orgId, planId, branch); err != nil {\n    branch = \"main\" // fall back to default branch\n}\nmsg, err := db.StoreConvoMessage(ctx, msg, branch, true)","handlingStrategy":"try-catch","validationCode":"if branch == \"\" || msg == \"\" {\n    return fmt.Errorf(\"cannot store convo message: empty branch or message\")\n}\nif err := Conn.Ping(); err != nil {\n    return fmt.Errorf(\"db unavailable: %v\", err)\n}","typeGuard":null,"tryCatchPattern":"msg, err := db.StoreConvoMessage(ctx, m, branch, commit)\nif err != nil {\n    if strings.Contains(err.Error(), \"error adding convo tokens\") {\n        log.Printf(\"token accounting failed, message may be stored: %v\", err)\n        // retry only the token step or alert, don't duplicate the message\n    }\n    return err\n}","preventionTips":["Keep migrations current so token tables/columns exist","Validate branch names against existing plan branches before storing","Monitor DB connectivity and retry transient failures","Don't re-call StoreConvoMessage after this error — the message row is already written"],"tags":["database","postgresql","tokens"],"backgroundTag":"convo-token-store-failed","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}