multica-ai/multica · error
create CLI config directory: %w
Error message
create CLI config directory: %w
What it means
SaveCLIConfigForProfile could not create the profile directory tree (~/.multica/profiles/<name> or its task-local equivalent) with os.MkdirAll. The wrapped errno is usually EACCES or ENOTDIR. This is the first write-path step, before any file is produced.
Source
Thrown at server/internal/cli/config.go:328
// SaveCLIConfig writes the CLI config to disk atomically (default profile).
func SaveCLIConfig(cfg CLIConfig) error {
return SaveCLIConfigForProfile(cfg, "")
}
// SaveCLIConfigForProfile writes the CLI config for the given profile.
func SaveCLIConfigForProfile(cfg CLIConfig, profile string) error {
path, err := CLIConfigPathForProfile(profile)
if err != nil {
return err
}
dir := filepath.Dir(path)
dirMode := os.FileMode(0o755)
if strings.TrimSpace(os.Getenv(TaskConfigRootEnv)) != "" {
dirMode = 0o700
}
if err := os.MkdirAll(dir, dirMode); err != nil {
return fmt.Errorf("create CLI config directory: %w", err)
}
if dirMode == 0o700 {
root, _, err := multicaConfigRoot()
if err != nil {
return fmt.Errorf("resolve task-local CLI config root: %w", err)
}
for current := dir; ; current = filepath.Dir(current) {
if err := os.Chmod(current, 0o700); err != nil {
return fmt.Errorf("restrict task-local CLI config directory: %w", err)
}
if current == root {
break
}
parent := filepath.Dir(current)
if parent == current {
return fmt.Errorf("task-local CLI config directory %q escapes root %q", dir, root)
}
}View on GitHub (pinned to 2c0912b6ec)
Solutions
- Check the exact path from the wrapped error; ensure every existing component is a directory and owned/writable by the current user
- chown -R $(whoami) the config root if a sudo run changed ownership
- Remove any plain file blocking a directory component (e.g. rm ~/.multica/profiles if it is a file)
- Free disk space or remount the home directory read-write if that is the underlying errno
Example fix
# before $ multica config set default_workspace acme create CLI config directory: mkdir /home/user/.multica/profiles: permission denied # after $ sudo chown -R $(whoami) ~/.multica $ multica config set default_workspace acme
Defensive patterns
Strategy: validation
Validate before calling
dir := filepath.Dir(configPath)
if info, err := os.Stat(filepath.Dir(dir)); err == nil && !info.IsDir() {
// a file occupies a parent component; fail early with a clear message
} Try / catch
if err := cli.SaveCLIConfig(cfg); err != nil {
if errors.Is(err, os.ErrPermission) || strings.Contains(err.Error(), "create CLI config directory") {
// guide the user to fix ownership of the config root
}
return err
} Prevention
- Create the config root once at install time with correct ownership
- Avoid mixing sudo and non-sudo invocations against the same home config
- For task-local roots, have the daemon mkdir and chown the tree before spawning CLI subprocesses
When it happens
Trigger: Calling SaveCLIConfig/SaveCLIConfigForProfile when the home directory or an ancestor of the target path is read-only, when a non-directory file occupies a path component (e.g. a file named 'profiles'), or when permissions deny creation.
Common situations: Home dir mounted read-only or full (ENOSPC surfaces similarly); earlier root-run invocation created ~/.multica as root:root 755 so the normal user cannot add subdirectories; MULTICA_TASK_CONFIG_ROOT pointing into a path where a component is a plain file.
Related errors
- read CLI config: %w
- mint PAT: target API URL not set
- mint PAT: response missing token
- daemon profile is not resolved yet; token sync skipped
- runtime local skill discovery timed out
AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15).
Data as JSON: /api/errors/914b7a9393b2f50e.
Report an issue: GitHub.