multica-ai/multica · error

read skill archive: %w

Error message

read skill archive: %w

What it means

Returned by `multica skill import --file <path>` when `os.ReadFile` on the local archive fails. The wrapped error is a standard Go filesystem error: `no such file or directory`, `permission denied`, or `is a directory`. This happens before any bytes hit the network.

Source

Thrown at server/cmd/multica/cmd_skill.go:476

	switch {
	case importURL == "" && importFile == "":
		return fmt.Errorf("either --url or --file is required")
	case importURL != "" && importFile != "":
		return fmt.Errorf("--url and --file are mutually exclusive")
	}
	onConflict, _ := cmd.Flags().GetString("on-conflict")
	if !validSkillImportConflictStrategy(onConflict) {
		return fmt.Errorf("--on-conflict must be one of: fail, overwrite, rename, skip")
	}

	ctx, cancel := context.WithTimeout(context.Background(), cli.AtLeastAPITimeout(60*time.Second))
	defer cancel()

	var result map[string]any
	if importFile != "" {
		fileData, readErr := os.ReadFile(importFile)
		if readErr != nil {
			return fmt.Errorf("read skill archive: %w", readErr)
		}
		if err := client.ImportSkillFile(ctx, fileData, filepath.Base(importFile), onConflict, &result); err != nil {
			if handledErr := handleSkillImportError(cmd, err); handledErr != nil {
				return handledErr
			}
			return fmt.Errorf("import skill: %w", err)
		}
		return printSkillImportResult(cmd, result)
	}

	body := map[string]any{
		"url":         importURL,
		"on_conflict": onConflict,
	}
	if err := client.PostJSON(ctx, "/api/skills/import", body, &result); err != nil {
		if handledErr := handleSkillImportError(cmd, err); handledErr != nil {
			return handledErr
		}

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Verify the file exists and is readable at that exact path: `ls -la <path>` from the same shell/cwd.
  2. Use an absolute path to eliminate cwd ambiguity.
  3. Expand `~` yourself (`$HOME/Downloads/skill.zip`) if the path was quoted.
  4. Check permissions if ls shows the file but ReadFile still fails (`chmod +r` or adjust ownership).

Example fix

# before
multica skill import --file skill.zip   # wrong cwd

# after
multica skill import --file "$(pwd)/downloads/skill.zip"
Defensive patterns

Strategy: validation

Validate before calling

test -f "$ARCHIVE" || { echo "archive not found: $ARCHIVE"; exit 1; }
test -r "$ARCHIVE" || { echo "archive unreadable: $ARCHIVE"; exit 1; }
multica skill import --file "$(realpath "$ARCHIVE")"

Try / catch

If the read still fails inside the CLI, inspect errno in the wrapped message: ENOENT → fix path/cwd; EACCES → fix permissions; EISDIR → point at the archive file itself.

Prevention

When it happens

Trigger: Passing a path that does not exist (typo, wrong cwd since relative paths resolve against the current directory); pointing at a directory instead of the archive file; file unreadable due to ownership/permissions; path with unexpanded `~` (the shell does not expand `~/…` inside quotes).

Common situations: Running the CLI from a different working directory than where the archive was downloaded; CI runner checking out the repo without the artifact; `"~/Downloads/skill.zip"` quoted so tilde never expands; permission mismatch when running under a different user or container.

Related errors


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