plandex-ai/plandex · error
error unmarshalling convo file: %v
Error message
error unmarshalling convo file: %v
What it means
A convo file was read successfully but json.Unmarshal could not decode it into the ConvoMessage struct. The invalid file is reported through errCh and the whole GetPlanConvo call fails wrapped as 'error reading convo files'. This is a data-integrity error: the stored JSON does not match the current ConvoMessage schema.
Source
Thrown at app/server/db/convo_helpers.go:58
defer func() {
if r := recover(); r != nil {
log.Printf("panic in GetPlanConvo: %v\n%s", r, debug.Stack())
errCh <- fmt.Errorf("panic in GetPlanConvo: %v\n%s", r, debug.Stack())
runtime.Goexit() // don't allow outer function to continue and double-send to channel
}
}()
bytes, err := os.ReadFile(filepath.Join(convoDir, file.Name()))
if err != nil {
errCh <- fmt.Errorf("error reading convo file: %v", err)
return
}
var convoMessage ConvoMessage
err = json.Unmarshal(bytes, &convoMessage)
if err != nil {
errCh <- fmt.Errorf("error unmarshalling convo file: %v", err)
return
}
convoCh <- &convoMessage
}(file)
}
for i := 0; i < len(files); i++ {
select {
case err := <-errCh:
return nil, fmt.Errorf("error reading convo files: %v", err)
case convoMessage := <-convoCh:
convo = append(convo, convoMessage)
}
}
sort.Slice(convo, func(i, j int) bool {View on GitHub (pinned to e2d772072e)
Solutions
- Identify the corrupt file (wrapped underlying error names the JSON offset/type) and delete or repair it
- Validate the file with 'jq . <file>.json' to see the exact JSON syntax problem
- Restore the file from backup if it was truncated
- Run any available Plandex data-migration for plans after a version upgrade
- Add schema-defaulting (e.g. disallowunknownfields off, per-field pointers) if upgrading across schema changes
Example fix
// inspect corrupt file
// before
json.Unmarshal(bytes, &convoMessage)
// after
if err := json.Unmarshal(bytes, &convoMessage); err != nil {
log.Printf("corrupt convo file %s: %v", file.Name(), err)
}
if err := json.Unmarshal(bytes, &convoMessage); err != nil {
errCh <- fmt.Errorf("error unmarshalling convo file: %v", err)
} Defensive patterns
Strategy: validation
Validate before calling
info, err := os.Stat(path)
if err == nil && info.Size() == 0 {
return fmt.Errorf("truncated convo file: %s", path)
}
var probe map[string]any
if data, err := os.ReadFile(path); err == nil {
if err := json.Unmarshal(data, &probe); err != nil {
return fmt.Errorf("corrupt convo file %s: %w", path, err)
}
} Type guard
func isConvoMessage(b []byte) bool {
var m db.ConvoMessage
return json.Unmarshal(b, &m) == nil && m.Id != ""
} Try / catch
convo, err := db.GetPlanConvo(orgId, planId)
if err != nil {
if strings.Contains(err.Error(), "unmarshalling convo file") {
// locate corrupt file, back it up, remove it, retry
quarantineCorruptConvoFiles(convoDir)
convo, err = db.GetPlanConvo(orgId, planId)
}
return err
} Prevention
- Never hand-edit message JSON in the data dir
- Write files atomically (temp file + rename) when forking the storage code
- Run data migrations after Plandex upgrades before serving traffic
- Validate backups restore to parseable JSON
- Monitor for zero-length files after server crashes
When it happens
Trigger: os.ReadFile succeeds but the bytes are not valid JSON matching ConvoMessage: zero-length/truncated file from an interrupted write, manually edited file, schema change after a version upgrade (field type changed), or a non-JSON file (editor swap file, .DS_Store-style artifact) dropped into the convo dir.
Common situations: Server crash or power loss during StoreConvoMessage leaving a partial JSON file; downgrading/upgrading Plandex so old or new field types no longer unmarshal; operator editing message JSON by hand; backup/restore tooling corrupting files.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- error unmarshalling convo message: %v
- error unmarshalling apply file: %v
- error unmarshalling accounts.json: %v
- refresh failed - marshal: %w
- error marshalling models: %v
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/5344d2438f640c56.
Report an issue: GitHub.