multica-ai/multica · error
upsert skill file: %w
Error message
upsert skill file: %w
What it means
Returned by `multica skill files upsert` when the PUT to `/api/skills/{id}/files` with `{path, content}` fails. Client-side validation already guaranteed non-empty path and content, so this is a server-side or transport failure: 404 (bad skill ID or path rejected), 400 (path violates server rules, e.g. absolute path, `..` traversal, or disallowed extension), auth, or timeout.
Source
Thrown at server/cmd/multica/cmd_skill.go:700
content, hasContent, err := resolveSkillContentFlag(cmd)
if err != nil {
return err
}
if !hasContent || content == "" {
return fmt.Errorf("--content is required")
}
body := map[string]any{
"path": filePath,
"content": content,
}
ctx, cancel := cli.APIContext(context.Background())
defer cancel()
var result map[string]any
if err := client.PutJSON(ctx, "/api/skills/"+args[0]+"/files", body, &result); err != nil {
return fmt.Errorf("upsert skill file: %w", err)
}
output, _ := cmd.Flags().GetString("output")
if output == "json" {
return cli.PrintJSON(os.Stdout, result)
}
fmt.Printf("Skill file upserted: %s (%s)\n", strVal(result, "path"), strVal(result, "id"))
return nil
}
func runSkillFilesDelete(cmd *cobra.Command, args []string) error {
client, err := newAPIClient(cmd)
if err != nil {
return err
}
ctx, cancel := cli.APIContext(context.Background())View on GitHub (pinned to 2c0912b6ec)
Solutions
- Make --path bundle-relative and traversal-free (no leading `/`, no `..`): e.g. `references/api.md`.
- Confirm the skill ID exists via `multica skill get <id>`.
- For large content, pipe through the file/stdin content source instead of a giant inline flag.
- Read the wrapped error: 400 = payload/path rejected, 404 = bad ID, connection errors = environment.
Example fix
# before multica skill files upsert sk-1 --path /home/me/notes.md --content "..." # after multica skill files upsert sk-1 --path notes.md --content "..."
Defensive patterns
Strategy: validation
Validate before calling
case "$BUNDLE_PATH" in /*|*..*) echo 'path must be bundle-relative without ..'; exit 1;; esac
[ "${#CONTENT}" -lt 1000000 ] || { echo 'content too large for inline flag; use a file source'; exit 1; }
multica skill get "$SKILL_ID" > /dev/null || exit 1 Try / catch
Branch on wrapped status: 400 → fix the path shape (relative, no traversal, allowed extension); 404 → re-resolve the skill ID; connection/timeout → environment or content size. Capture the server's response detail from the error text before retrying anything.
Prevention
- Use bundle-relative paths without leading slash or '..' segments.
- Resolve skill IDs fresh before upserting.
- Route large content through file/stdin sources instead of a giant inline --content string.
When it happens
Trigger: Upserting to a skill ID that does not exist; using --path `/etc/passwd`, `../secrets`, or another traversal-shaped value the server rejects; very large content exceeding server body limits; transport/auth failure.
Common situations: Using a local absolute file path as --path instead of a bundle-relative one; migrating content between environments with different skill IDs; pasting a multi-megabyte file as an inline --content argument exceeding shell or server limits.
Related errors
AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15).
Data as JSON: /api/errors/b01fc26f75c1e4de.
Report an issue: GitHub.