multica-ai/multica · error

resolve %s %q: user home: %w

Error message

resolve %s %q: user home: %w

What it means

resolveCodexConfigPath expands a ~/ or ~\-prefixed config path and needs the current user's home directory; os.UserHomeDir failed, typically because $HOME (or %USERPROFILE% on Windows) is unset or empty in the daemon's environment.

Source

Thrown at server/internal/daemon/execenv/codex_home.go:1222

		return fmt.Errorf("close codex models cache binding %s: %w", path, err)
	}
	return nil
}

// resolveCodexConfigPath maps a path-valued config.toml entry to its source
// file on this host. key is the config key the path came from and only shapes
// the diagnostics, so an operator reading a failure knows which setting to fix.
// A relative path resolves against the shared Codex home — that is the
// directory the config was copied from, and the base Codex itself would have
// used before the per-task home relocated CODEX_HOME.
func resolveCodexConfigPath(configPath, sharedHome, key string) (string, error) {
	if filepath.IsAbs(configPath) {
		return filepath.Clean(configPath), nil
	}
	if strings.HasPrefix(configPath, "~/") || strings.HasPrefix(configPath, `~\`) {
		home, err := os.UserHomeDir()
		if err != nil {
			return "", fmt.Errorf("resolve %s %q: user home: %w", key, configPath, err)
		}
		return filepath.Join(home, configPath[2:]), nil
	}
	if strings.HasPrefix(configPath, "~") {
		return "", fmt.Errorf("%s %q uses unsupported ~user expansion", key, configPath)
	}
	return filepath.Join(sharedHome, filepath.Clean(configPath)), nil
}

func exposeSharedCodexPluginCache(codexHome, sharedHome string) error {
	src := filepath.Join(sharedHome, "plugins", "cache")
	dst := filepath.Join(codexHome, "plugins", "cache")
	if err := os.MkdirAll(src, 0o755); err != nil {
		return fmt.Errorf("create shared plugin cache dir: %w", err)
	}
	if err := os.MkdirAll(filepath.Dir(dst), 0o755); err != nil {
		return fmt.Errorf("create codex plugin dir: %w", err)
	}

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Set HOME (or USERPROFILE on Windows) in the daemon's service environment
  2. Change the Codex config value to an absolute path instead of ~/...
  3. Run the daemon under a properly provisioned user account

Example fix

// before (config.toml)
model_provider_file = "~/codex/providers.json"

// after
model_provider_file = "/home/daemon/codex/providers.json"
Defensive patterns

Strategy: validation

Validate before calling

if os.UserHomeDir() != nil {
	return fmt.Errorf("HOME unset; cannot resolve ~/ paths in codex config")
}

Prevention

When it happens

Trigger: Daemon process launched by systemd or a container without HOME set; environment scrubbed by a service manager; running as a user with no passwd entry.

Common situations: systemd unit missing Environment=HOME=...; Docker image without HOME; CI runners that clear the environment.

Related errors


AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15). Data as JSON: /api/errors/f7d0b2444e44fd02. Report an issue: GitHub.