plandex-ai/plandex · error

error creating directory: %v

Error message

error creating directory: %v

What it means

WriteCustomModelsFile creates the parent directory of the target custom-models JSON with os.MkdirAll(..., 0755) before writing; a directory-creation failure is wrapped as 'error creating directory: %v'.

Source

Thrown at app/cli/lib/custom_models.go:138

	if err != nil && !os.IsNotExist(err) {
		return CustomModelsCheckLocalChangesResult{}, fmt.Errorf("error reading hash file: %v", err)
	}

	currentHash, err := localModelsInput.Hash()
	if err != nil {
		return CustomModelsCheckLocalChangesResult{}, fmt.Errorf("error hashing models: %v", err)
	}

	return CustomModelsCheckLocalChangesResult{
		HasLocalChanges:  currentHash != string(lastSavedHash),
		LocalModelsInput: localModelsInput,
	}, nil
}

func WriteCustomModelsFile(path string, modelsInput *shared.ModelsInput) error {
	err := os.MkdirAll(filepath.Dir(path), 0755)
	if err != nil {
		return fmt.Errorf("error creating directory: %v", err)
	}

	clientModelsInput := modelsInput.ToClientModelsInput()
	clientModelsInput.PrepareUpdate()

	jsonData, err := json.MarshalIndent(clientModelsInput, "", "  ")
	if err != nil {
		return fmt.Errorf("error marshalling models: %v", err)
	}

	err = os.WriteFile(path, jsonData, 0644)
	if err != nil {
		return fmt.Errorf("error writing file: %v", err)
	}

	err = SaveCustomModelsHash(path, modelsInput)
	if err != nil {
		return fmt.Errorf("error saving hash file: %v", err)

View on GitHub (pinned to e2d772072e)

Solutions

  1. Check the wrapped OS error (%v) for the exact mkdir failure
  2. Verify filepath.Dir(path) is writable and no file occupies a directory component of the path
  3. Fix permissions (chmod/chown) or free disk space if that is the cause
  4. Correct HOME/config-path configuration so the directory lands somewhere writable

Example fix

// before
err := os.MkdirAll(filepath.Dir(path), 0755)
if err != nil {
    return fmt.Errorf("error creating directory: %v", err)
}
// after: caller preflight
if info, err := os.Stat(filepath.Dir(path)); err == nil && !info.IsDir() {
    os.Remove(filepath.Dir(path)) // file blocking directory creation
}
Defensive patterns

Strategy: validation

Validate before calling

dir := filepath.Dir(path)
if info, err := os.Stat(dir); err == nil && !info.IsDir() {
    return fmt.Errorf("%s exists and is not a directory", dir)
}
if err := syscall.Access(dir, syscall.O_RDWR); err != nil {
    return fmt.Errorf("directory not writable: %s", dir)
}

Type guard

func dirWritable(path string) bool {
    info, err := os.Stat(path)
    if err != nil || !info.IsDir() {
        return false
    }
    return info.Mode().Perm()&0200 != 0
}

Try / catch

err := WriteCustomModelsFile(path, modelsInput)
if err != nil && strings.Contains(err.Error(), "error creating directory") {
    fmt.Fprintf(os.Stderr, "cannot create %s — check permissions/disk: %v\n", filepath.Dir(path), err)
    os.Exit(1)
}

Prevention

When it happens

Trigger: os.MkdirAll(filepath.Dir(path), 0755) fails — parent path component is a file, permission denied, read-only filesystem, or invalid path characters.

Common situations: Config directory path exists as a regular file; HOME misconfigured to a non-writable location; disk full or mounted read-only; sandboxed/containerized environments with restricted filesystem writes.

Related errors


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