plandex-ai/plandex · error

error creating applies dir: %v

Error message

error creating applies dir: %v

What it means

ApplyPlan persists a PlanApply record as JSON under the plan's applies directory. Before writing the file it calls os.MkdirAll(appliesDir, 0755); if the directory cannot be created the underlying OS error is wrapped with this message. The library throws it because it cannot store the apply record without the directory existing.

Source

Thrown at app/server/db/result_helpers.go:752

	for _, desc := range convoMessageDescriptions {
		descriptionIds = append(descriptionIds, desc.Id)
		messageIds = append(messageIds, desc.ConvoMessageId)
	}

	planApply.PlanFileResultIds = resultIds
	planApply.ConvoMessageDescriptionIds = descriptionIds
	planApply.ConvoMessageIds = messageIds

	// Store the PlanApply object
	bytes, err := json.MarshalIndent(planApply, "", "  ")
	if err != nil {
		return fmt.Errorf("error marshalling plan apply: %v", err)
	}

	appliesDir := getPlanAppliesDir(orgId, planId)
	err = os.MkdirAll(appliesDir, 0755)
	if err != nil {
		return fmt.Errorf("error creating applies dir: %v", err)
	}

	err = os.WriteFile(filepath.Join(appliesDir, planApply.Id+".json"), bytes, 0644)
	if err != nil {
		return fmt.Errorf("error writing plan apply file: %v", err)
	}

	msg := "✅ Marked pending results as applied"

	currentFiles := currentPlanState.CurrentPlanFiles.Files
	var sortedFiles []string
	for path := range currentFiles {
		sortedFiles = append(sortedFiles, path)
	}
	sort.Strings(sortedFiles)
	for _, path := range sortedFiles {
		msg += fmt.Sprintf("\n • 📄 %s", path)
	}

View on GitHub (pinned to e2d772072e)

Solutions

  1. Check permissions/ownership on the plan data root (getPlanAppliesDir target) and grant the process write access
  2. Verify the path segment where the applies dir belongs is a directory, not a regular file; remove/rename the conflicting file
  3. Check disk space/quota (df -h, quota reports) on the volume
  4. Inspect the wrapped %v cause (EACCES vs ENOSPC vs ENOTDIR) and fix accordingly

Example fix

// before: blindly writing into a path that may be a file
appliesDir := getPlanAppliesDir(orgId, planId)
err = os.MkdirAll(appliesDir, 0755)
// after: detect a file blocking the dir and recreate
if fi, statErr := os.Stat(appliesDir); statErr == nil && !fi.IsDir() {
    if rmErr := os.Remove(appliesDir); rmErr != nil {
        return fmt.Errorf("applies path is a file and cannot be removed: %v", rmErr)
    }
}
err = os.MkdirAll(appliesDir, 0755)
Defensive patterns

Strategy: validation

Validate before calling

appliesDir := getPlanAppliesDir(orgId, planId)
if fi, err := os.Stat(filepath.Dir(appliesDir)); err != nil || !fi.IsDir() {
    return fmt.Errorf("applies parent path invalid: %v", err)
}
if err := unix.Access(filepath.Dir(appliesDir), unix.W_OK); err != nil {
    return fmt.Errorf("no write access to %s: %v", filepath.Dir(appliesDir), err)
}

Try / catch

if err := os.MkdirAll(appliesDir, 0755); err != nil {
    var pathErr *os.PathError
    if errors.As(err, &pathErr) {
        log.Printf("mkdir failed op=%s path=%s: %v", pathErr.Op, pathErr.Path, pathErr.Err)
    }
    return fmt.Errorf("error creating applies dir: %v", err)
}

Prevention

When it happens

Trigger: os.MkdirAll fails inside ApplyPlan — e.g. the parent org/plan directory path contains a file where a directory is expected, the process lacks write permission on the data root, the disk is full, or the path exceeds filesystem length limits.

Common situations: Read-only mounts or containers running as non-root without ownership of the app data dir; a stale file (not dir) named like the applies dir; SELinux/AppArmor blocking writes; disk quota exceeded on the volume holding plan data.

Understand the failure class

Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.

Related errors


AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/c1d6dfe0d9523809. Report an issue: GitHub.