multica-ai/multica · error
parse response: %w
Error message
parse response: %w
What it means
After a 200 response from the daemon, runRepoCheckout json.Unmarshals the body into {path, branch_name}. This fails when the body is not valid JSON — i.e. the daemon returned 200 with a non-JSON payload (proxy interpolation, HTML error page, or a version-skewed daemon returning a different serialization).
Source
Thrown at server/cmd/multica/cmd_repo.go:418
case <-ctx.Done():
timer.Stop()
return fmt.Errorf("connect to daemon: %w", context.Cause(ctx))
case <-timer.C:
continue
}
}
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("checkout failed: %s", string(body))
}
break
}
var result struct {
Path string `json:"path"`
BranchName string `json:"branch_name"`
}
if err := json.Unmarshal(body, &result); err != nil {
return fmt.Errorf("parse response: %w", err)
}
fmt.Fprintf(os.Stdout, "%s\n", result.Path)
fmt.Fprintf(os.Stderr, "Checked out %s → %s (branch: %s)\n", repoURL, result.Path, result.BranchName)
return nil
}
func repoCheckoutRetryDelay(value string, now time.Time) time.Duration {
const (
defaultDelay = time.Second
maxDelay = 30 * time.Second
)
value = strings.TrimSpace(value)
if seconds, err := strconv.Atoi(value); err == nil && seconds >= 0 {
return min(time.Duration(seconds)*time.Second, maxDelay)
}
if retryAt, err := http.ParseTime(value); err == nil {View on GitHub (pinned to 2c0912b6ec)
Solutions
- Confirm the port really belongs to the multica daemon: curl -s http://127.0.0.1:$MULTICA_DAEMON_PORT/repo/checkout and inspect what answers; fix the port collision.
- Upgrade/downgrade CLI and daemon to matching versions so the response contract ({path, branch_name}) holds.
- Re-run inside a fresh daemon task so MULTICA_DAEMON_PORT is injected by the real daemon.
Example fix
# before: another process owns the port MULTICA_DAEMON_PORT=8080 multica repo checkout URL # parse response: invalid character '<' # after: use the daemon's actual port ss -ltnp | grep multica # e.g. 8123 MULTICA_DAEMON_PORT=8123 multica repo checkout URL
Defensive patterns
Strategy: try-catch
Validate before calling
if !json.Valid(body) {
return fmt.Errorf("daemon returned non-JSON (wrong port or version?): %.120s", body)
} Type guard
type checkoutResult struct {
Path string `json:"path"`
BranchName string `json:"branch_name"`
}
func isCheckoutResult(v any) (checkoutResult, bool) {
r, ok := v.(checkoutResult)
return r, ok && r.Path != ""
} Try / catch
if err := json.Unmarshal(body, &result); err != nil {
return fmt.Errorf("parse response: %w (raw: %.120s)", err, body) // keep raw body for diagnosis
} Prevention
- Verify the port belongs to the multica daemon before calling (curl the endpoint).
- Keep daemon and CLI versions matched so the JSON contract holds.
- Log a body prefix on parse failure to identify port collisions fast.
When it happens
Trigger: A proxy/sidecar on 127.0.0.1 intercepts the port and answers 200 with HTML; an older/newer daemon binary whose /repo/checkout success payload is not the expected JSON; a truncated body after a transport hiccup (though ReadAll would usually catch that first).
Common situations: Another service already bound to the port the env var points at (port collision), so the CLI talks to the wrong process; mixed-version deployments during rolling upgrades of the daemon.
Related errors
- parse CLI config: %w
- daemon exited during startup.
- repo is not configured for this workspace
- local_directory: local_path is empty
- ErrRepoBusy
AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15).
Data as JSON: /api/errors/89d3b77e01985af8.
Report an issue: GitHub.