plandex-ai/plandex · error

error creating results dir: %v

Error message

error creating results dir: %v

What it means

StorePlanResult persists a PlanFileResult as JSON under the plan's results directory. Before writing the file it calls os.MkdirAll(resultsDir, 0755); if that fails (e.g. permissions, read-only filesystem, invalid path) it wraps the OS error with this message.

Source

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

	now := time.Now()
	if result.Id == "" {
		result.Id = uuid.New().String()
		result.CreatedAt = now
	}
	result.UpdatedAt = now

	bytes, err := json.MarshalIndent(result, "", "  ")

	if err != nil {
		return fmt.Errorf("error marshalling result: %v", err)
	}

	resultsDir := getPlanResultsDir(result.OrgId, result.PlanId)

	err = os.MkdirAll(resultsDir, 0755)

	if err != nil {
		return fmt.Errorf("error creating results dir: %v", err)
	}

	log.Printf("Storing plan result: %s - %s", result.Path, result.Id)

	err = os.WriteFile(filepath.Join(resultsDir, result.Id+".json"), bytes, 0644)

	if err != nil {
		return fmt.Errorf("error writing result file: %v", err)
	}

	return nil

}

type CurrentPlanStateParams struct {
	OrgId                    string
	PlanId                   string
	PlanFileResults          []*PlanFileResult

View on GitHub (pinned to e2d772072e)

Solutions

  1. Check the wrapped OS error (os.PathError) for the actual path and errno (EACCES/EROFS/ENOSPC/ENOTDIR)
  2. Verify the process user has write access to the plans data root directory
  3. Ensure the results path is not blocked by an existing regular file with the same name
  4. Free disk space or remount the volume read-write
  5. Validate OrgId/PlanId before calling so the derived path is sane

Example fix

// before
if err := db.StorePlanResult(result); err != nil {
	log.Printf("store failed: %v", err)
}
// after
if err := os.MkdirAll(filepath.Dir(getPlanResultsDir(orgId, planId)), 0755); err != nil {
	return fmt.Errorf("data dir not writable: %w", err)
}
if err := db.StorePlanResult(result); err != nil {
	log.Printf("store failed: %v", err)
}
Defensive patterns

Strategy: validation

Validate before calling

func canStoreResults(orgId, planId string) error {
	dir := getPlanResultsDir(orgId, planId)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("results dir not creatable: %w", err)
	}
	f, err := os.CreateTemp(dir, ".probe-*")
	if err != nil {
		return err
	}
	f.Close()
	os.Remove(f.Name())
	return nil
}

Type guard

func isPathError(err error) *os.PathError {
	var pe *os.PathError
	if errors.As(err, &pe) {
		return pe
	}
	return nil
}

Try / catch

if err := db.StorePlanResult(result); err != nil {
	if pe := isPathError(err); pe != nil && errors.Is(pe.Err, syscall.EACCES) {
		return fmt.Errorf("fix permissions on %s: %w", pe.Path, err)
	}
	return err
}

Prevention

When it happens

Trigger: Calling StorePlanResult with an OrgId/PlanId that resolves to a results dir path which cannot be created: parent directory not writable, disk full, results path is a file instead of a directory, or the org plan path contains invalid characters.

Common situations: Server running as a user without write permission on the plans data directory; DATA_DIR mounted read-only (container volume misconfig); corrupted org/plan IDs producing a bogus path; full disk on the host.

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/d94bd76542098e56. Report an issue: GitHub.