plandex-ai/plandex · error
error reading applies dir: %v
Error message
error reading applies dir: %v
What it means
GetPlanApplies reads the plan's applies directory with os.ReadDir. Missing directories (os.IsNotExist) are treated as "no applies" and return nil, nil; any OTHER read error is wrapped as this error. It means the directory exists (or otherwise failed) but could not be listed — typically permissions or I/O problems.
Source
Thrown at app/server/db/result_helpers.go:1038
}
if !foundReplacement {
return fmt.Errorf("replacement not found: %s", replacementId)
}
return nil
}
func GetPlanApplies(orgId, planId string) ([]*PlanApply, error) {
appliesDir := getPlanAppliesDir(orgId, planId)
files, err := os.ReadDir(appliesDir)
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, fmt.Errorf("error reading applies dir: %v", err)
}
planApplies := []*PlanApply{}
var mu sync.Mutex
errCh := make(chan error, len(files))
for _, file := range files {
go func(file os.DirEntry) {
defer func() {
if r := recover(); r != nil {
log.Printf("panic in GetPlanApplies: %v\n%s", r, debug.Stack())
errCh <- fmt.Errorf("panic in GetPlanApplies: %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(appliesDir, file.Name()))
View on GitHub (pinned to e2d772072e)
Solutions
- Check permissions on <planDir>/applies and its parents (server process user needs read+execute).
- Verify the path is a directory, not a file: 'ls -la' / 'stat' on the applies path.
- Check disk health / dmesg for I/O errors if failures are intermittent.
- Fix ownership to match the server process user.
Example fix
// before applies, err := db.GetPlanApplies(orgId, planId) // after (pre-check on host) // stat <data>/orgs/<orgId>/plans/<planId>/applies && ensure it is a dir with correct perms applies, err := db.GetPlanApplies(orgId, planId)
Defensive patterns
Strategy: validation
Validate before calling
appliesPath := filepath.Join(getPlanDir(orgId, planId), "applies")
if info, err := os.Stat(appliesPath); err == nil && !info.IsDir() {
return fmt.Errorf("%s is not a directory", appliesPath)
}
applies, err := GetPlanApplies(orgId, planId) Try / catch
applies, err := GetPlanApplies(orgId, planId)
if err != nil {
if strings.Contains(err.Error(), "error reading applies dir") {
return nil, fmt.Errorf("cannot list applies dir (check permissions/path): %w", err)
}
return nil, err
} Prevention
- Ensure the server process user owns or has read+execute on the plan data directories.
- Run filesystem health checks if errors are intermittent.
- Don't replace data directories with regular files during maintenance.
When it happens
Trigger: Calling GetPlanApplies when the applies directory exists but ReadDir fails for a non-not-exist reason: permission denied, path is a file not a directory, or an I/O/disk error.
Common situations: Manual intervention replaced the applies directory with a regular file; chmod/chown changes on the data dir; running the server under a different user than the one that created the data.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- error walking directory: %s
- failed to check if %s exists: %s
- failed to read %s: %s
- failed to write %s: %s
- failed to remove %s: %s
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/0b312b7ee6550c5f.
Report an issue: GitHub.