multica-ai/multica · error
restrict task-local CLI config directory: %w
Error message
restrict task-local CLI config directory: %w
What it means
In task-local mode (MULTICA_TASK_CONFIG_ROOT set) the save path walks from the config directory up to the task root, chmod'ing each level to 0700 so the daemon-private config is not world-readable. This error means one of those os.Chmod calls failed, typically with EPERM because the directory is owned by another user.
Source
Thrown at server/internal/cli/config.go:337
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)
}
}
}
data, err := json.MarshalIndent(cfg, "", " ")
if err != nil {
return fmt.Errorf("encode CLI config: %w", err)
}
// Write to a temp file in the same directory, then rename for atomicity.
tmp, err := os.CreateTemp(dir, ".config-*.json.tmp")
if err != nil {View on GitHub (pinned to 2c0912b6ec)
Solutions
- Align ownership: chown the entire task root to the user the CLI runs as
- Run the save as the same user that owns the directory chain
- Point MULTICA_TASK_CONFIG_ROOT at a plain local directory (ext4/apfs) rather than a network/FUSE mount
- If 0700 restriction is not needed for your setup, unset MULTICA_TASK_CONFIG_ROOT to use the standard 0755 home layout
Example fix
# before: daemon (root) created /var/lib/multica/tasks; CLI runs as 'multica' $ multica config set ... restrict task-local CLI config directory: chmod /var/lib/multica/tasks: operation not permitted # after $ sudo chown -R multica:multica /var/lib/multica/tasks
Defensive patterns
Strategy: validation
Validate before calling
root := os.Getenv("MULTICA_TASK_CONFIG_ROOT")
for p := root; ; p = filepath.Dir(p) {
if info, err := os.Stat(p); err != nil || info.Mode().Perm()&0o200 == 0 {
// ancestor not writable by this user; fix before saving
}
if p == "/" { break }
} Try / catch
if err := cli.SaveCLIConfig(cfg); err != nil && strings.Contains(err.Error(), "restrict task-local") {
// report ownership mismatch between CLI user and task-root owner
} Prevention
- Run the CLI as the same user that owns the task root
- Keep MULTICA_TASK_CONFIG_ROOT on a local POSIX filesystem
- Set up task roots with correct ownership during provisioning, not lazily at save time
When it happens
Trigger: Saving CLI config in task-local mode when a directory between the config dir and the root is owned by root or another user, or when running on a filesystem that does not support chmod (some NFS/FUSE/Windows mounts return EPERM).
Common situations: Daemon created the task root as root and then a CLI subprocess running as the service user tries to save config; MULTICA_TASK_CONFIG_ROOT pointing at a bind-mounted or network volume with restricted metadata operations.
Related errors
- mint PAT: response missing token
- daemon profile is not resolved yet; token sync skipped
- runtime local skill discovery timed out
- runtime local skill import failed
- resolve profile %q: %w
AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15).
Data as JSON: /api/errors/72188466c8559c18.
Report an issue: GitHub.