chenhg5/cc-connect · error

codex: mkdir codex home: %w

Error message

codex: mkdir codex home: %w

What it means

After resolving the codex home, ensureCodexProviderConfig calls os.MkdirAll(home, 0o755) to guarantee the directory exists before writing config.toml. If directory creation fails, this error wraps the OS reason. It indicates the codex home directory could not be created (permissions, path conflicts, read-only filesystem).

Source

Thrown at agent/codex/provider_config.go:24

	"log/slog"
	"os"
	"path/filepath"
	"strings"
)

// ensureCodexProviderConfig writes or updates a [model_providers.<name>] section
// in $CODEX_HOME/config.toml so that Codex CLI can use the provider's wire_api
// and http_headers settings.
func ensureCodexProviderConfig(codexHome, name, baseURL, wireAPI string, headers map[string]string) error {
	if name == "" {
		return nil
	}
	home, err := resolveCodexHomeForConfig(codexHome)
	if err != nil {
		return fmt.Errorf("codex: resolve codex home: %w", err)
	}
	if err := os.MkdirAll(home, 0o755); err != nil {
		return fmt.Errorf("codex: mkdir codex home: %w", err)
	}

	cfgPath := filepath.Join(home, "config.toml")
	raw, _ := os.ReadFile(cfgPath)
	content := string(raw)

	section := buildProviderSection(name, baseURL, wireAPI, headers)
	updated := upsertProviderSection(content, name, section)

	if err := os.WriteFile(cfgPath, []byte(updated), 0o644); err != nil {
		return fmt.Errorf("codex: write config.toml: %w", err)
	}
	slog.Debug("codex: wrote provider config", "provider", name, "path", cfgPath)
	return nil
}

// ensureCodexAuth writes $CODEX_HOME/auth.json with the provider's API key,
// matching cc-switch's approach: {"OPENAI_API_KEY": "...", "auth_mode": "api_key"}.

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Check the wrapped OS error: if permission denied, chown/chmod the parent directory or run as the correct user.
  2. Verify CODEX_HOME is a valid directory path, not an existing regular file.
  3. Ensure the filesystem containing CODEX_HOME is writable and not full.
  4. Pre-create the directory manually: mkdir -p ~/.codex.

Example fix

// before
Environment=CODEX_HOME=/mnt/ro/codex  # read-only mount
// after
Environment=CODEX_HOME=/home/alice/.codex  # writable
Defensive patterns

Strategy: validation

Validate before calling

home := os.Getenv("CODEX_HOME")
if home == "" { h, _ := os.UserHomeDir(); home = filepath.Join(h, ".codex") }
if fi, err := os.Stat(home); err == nil && !fi.IsDir() {
    return fmt.Errorf("CODEX_HOME %s is a file, not a directory", home)
}
if err := os.MkdirAll(home, 0o755); err != nil {
    return fmt.Errorf("cannot create codex home %s: %w", home, err)
}

Try / catch

if err := ensureCodexProviderConfig(home, name, baseURL, wireAPI, headers); err != nil {
    var pe *fs.PathError
    if errors.As(err, &pe) && errors.Is(pe.Err, syscall.EACCES) {
        return fmt.Errorf("fix permissions on %s: %w", home, err)
    }
    return err
}

Prevention

When it happens

Trigger: os.MkdirAll(home, 0o755) returns an error — parent directories not writable, a file exists at the home path, disk full, or the path is on a read-only mount — during StartSession provider setup or the corresponding tests.

Common situations: CODEX_HOME pointing at a read-only or nonexistent mount; permission-denied creating ~/.codex (restricted home dir); a regular file already exists at the CODEX_HOME path; running as a different user than expected in a container.

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 chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/6e7633a89a5b83ba. Report an issue: GitHub.