multica-ai/multica · error

resolve task-local CLI config root: %w

Error message

resolve task-local CLI config root: %w

What it means

While saving with MULTICA_TASK_CONFIG_ROOT set, the code needs the task-local root to chmod-restrict the created directories to 0700, but multicaConfigRoot() failed. In practice the only failure mode at this point is the env var being non-absolute (or the home directory being unresolvable in the fallback path).

Source

Thrown at server/internal/cli/config.go:333

// 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)
			}
		}
	}
	data, err := json.MarshalIndent(cfg, "", "  ")
	if err != nil {
		return fmt.Errorf("encode CLI config: %w", err)
	}

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Set MULTICA_TASK_CONFIG_ROOT to an absolute path (leading '/')
  2. If the task-local mode is unintended, unset MULTICA_TASK_CONFIG_ROOT entirely
  3. In minimal containers/CI, ensure HOME is set so the non-task fallback can resolve
  4. Validate the env var at daemon startup before spawning CLI subprocesses that inherit it

Example fix

# before
export MULTICA_TASK_CONFIG_ROOT=multica/tasks

# after
export MULTICA_TASK_CONFIG_ROOT=/var/lib/multica/tasks
Defensive patterns

Strategy: validation

Validate before calling

if root := strings.TrimSpace(os.Getenv("MULTICA_TASK_CONFIG_ROOT")); root != "" && !filepath.IsAbs(root) {
	// reject/fix the env var before any CLI invocation
	log.Fatal("MULTICA_TASK_CONFIG_ROOT must be an absolute path")
}

Prevention

When it happens

Trigger: MULTICA_TASK_CONFIG_ROOT set to a relative path (e.g. 'multica-tasks' or './run') while saving the CLI config; or the env var unset and os.UserHomeDir() failing because $HOME is empty.

Common situations: A daemon or wrapper exporting MULTICA_TASK_CONFIG_ROOT with a relative value; CI containers where HOME is not set; envsubst/scripts accidentally stripping the leading slash.

Related errors


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