plandex-ai/plandex · error
error reading description file %s: %v
Error message
error reading description file %s: %v
What it means
Inside each per-file goroutine of GetConvoMessageDescriptions, os.ReadFile loads the description JSON. Any read failure is wrapped as 'error reading description file %s: %v' naming the file and sent to errCh, which the collector turns into 'error reading description files: ...' and aborts the entire descriptions load.
Source
Thrown at app/server/db/result_helpers.go:340
errCh := make(chan error, len(files))
descCh := make(chan *ConvoMessageDescription, len(files))
for _, file := range files {
go func(file os.DirEntry) {
defer func() {
if r := recover(); r != nil {
log.Printf("panic in GetConvoMessageDescriptions: %v\n%s", r, debug.Stack())
errCh <- fmt.Errorf("panic in GetConvoMessageDescriptions: %v\n%s", r, debug.Stack())
runtime.Goexit() // don't allow outer function to continue and double-send to channel
}
}()
path := filepath.Join(descriptionsDir, file.Name())
bytes, err := os.ReadFile(path)
if err != nil {
errCh <- fmt.Errorf("error reading description file %s: %v", file.Name(), err)
return
}
var description ConvoMessageDescription
err = json.Unmarshal(bytes, &description)
if err != nil {
log.Println("Error unmarshalling description file:", path)
log.Println("bytes:")
log.Println(string(bytes))
errCh <- fmt.Errorf("error unmarshalling description file %s: %v", path, err)
return
}
descCh <- &description
}(file)
}View on GitHub (pinned to e2d772072e)
Solutions
- Identify the failing file from the message and check whether it still exists and is readable
- Check permissions/ownership of that file and the descriptions directory for the server user
- Remove non-regular entries (directories, sockets) from the descriptions dir or filter them with file.Type().IsRegular()
- Stop concurrent cleanup processes from racing with reads, or tolerate individual file misses by skipping on os.IsNotExist
- Investigate filesystem health if the inner error is an I/O error (EIO), remounting or repairing the volume
Example fix
// before
bytes, err := os.ReadFile(path)
if err != nil {
errCh <- fmt.Errorf("error reading description file %s: %v", file.Name(), err)
return
}
// after
bytes, err := os.ReadFile(path)
if err != nil {
if os.IsNotExist(err) {
descCh <- nil // file vanished between listing and read; skip it
return
}
errCh <- fmt.Errorf("error reading description file %s: %v", file.Name(), err)
return
} Defensive patterns
Strategy: validation
Validate before calling
func descriptionFileReadable(dir string, name string) error {
path := filepath.Join(dir, name)
info, err := os.Stat(path)
if err != nil {
return err
}
if !info.Mode().IsRegular() {
return fmt.Errorf("%s is not a regular file", path)
}
f, err := os.Open(path)
if err != nil {
return err
}
return f.Close()
} Type guard
func isDescriptionFileReadError(err error) bool {
return err != nil && strings.Contains(err.Error(), "error reading description file")
} Try / catch
descriptions, err := GetConvoMessageDescriptions(orgId, planId)
if err != nil {
if isDescriptionFileReadError(err) {
var badFile string
fmt.Sscanf(err.Error(), "error reading description files: error reading description file %s", &badFile)
log.Printf("unreadable description file %q; repair or remove it", badFile)
return nil, err
}
return nil, err
} Prevention
- Don't run cleanup jobs that delete description files while plan state is being read
- Keep volume read/write (not read-only remounted) for the plan data root
- Filter non-regular entries from descriptions directories
- Grant the server user read permission on all description files
When it happens
Trigger: Calling GetConvoMessageDescriptions when a listed description file cannot be read: it was deleted between ReadDir and ReadFile, permissions changed, it is a directory/special file inside descriptionsDir, or the underlying filesystem returns an I/O error.
Common situations: Another process (cleanup job, concurrent plan reset) deleting description files while this read runs; permission drift after container image updates or user changes; a subdirectory accidentally created inside descriptionsDir; read-only remount of the data volume.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- failed to read file %s: %v
- failed to read the file %s: %v
- error getting plan current branch: %v
- error reading convo files: %v
- error deleting draft plan dir: %v
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/7b995fd64c7379a8.
Report an issue: GitHub.