{"record":{"id":"89d3b77e01985af8","repo":"multica-ai/multica","slug":"parse-response-w","errorCode":null,"errorMessage":"parse response: %w","messagePattern":"parse response: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/cmd/multica/cmd_repo.go","lineNumber":418,"sourceCode":"\t\t\tcase <-ctx.Done():\n\t\t\t\ttimer.Stop()\n\t\t\t\treturn fmt.Errorf(\"connect to daemon: %w\", context.Cause(ctx))\n\t\t\tcase <-timer.C:\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tif resp.StatusCode != http.StatusOK {\n\t\t\treturn fmt.Errorf(\"checkout failed: %s\", string(body))\n\t\t}\n\t\tbreak\n\t}\n\n\tvar result struct {\n\t\tPath       string `json:\"path\"`\n\t\tBranchName string `json:\"branch_name\"`\n\t}\n\tif err := json.Unmarshal(body, &result); err != nil {\n\t\treturn fmt.Errorf(\"parse response: %w\", err)\n\t}\n\n\tfmt.Fprintf(os.Stdout, \"%s\\n\", result.Path)\n\tfmt.Fprintf(os.Stderr, \"Checked out %s → %s (branch: %s)\\n\", repoURL, result.Path, result.BranchName)\n\n\treturn nil\n}\n\nfunc repoCheckoutRetryDelay(value string, now time.Time) time.Duration {\n\tconst (\n\t\tdefaultDelay = time.Second\n\t\tmaxDelay     = 30 * time.Second\n\t)\n\tvalue = strings.TrimSpace(value)\n\tif seconds, err := strconv.Atoi(value); err == nil && seconds >= 0 {\n\t\treturn min(time.Duration(seconds)*time.Second, maxDelay)\n\t}\n\tif retryAt, err := http.ParseTime(value); err == nil {","sourceCodeStart":400,"sourceCodeEnd":436,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/cmd/multica/cmd_repo.go#L400-L436","documentation":"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).","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"# before: another process owns the port\nMULTICA_DAEMON_PORT=8080 multica repo checkout URL   # parse response: invalid character '<'\n\n# after: use the daemon's actual port\nss -ltnp | grep multica   # e.g. 8123\nMULTICA_DAEMON_PORT=8123 multica repo checkout URL","handlingStrategy":"try-catch","validationCode":"if !json.Valid(body) {\n\treturn fmt.Errorf(\"daemon returned non-JSON (wrong port or version?): %.120s\", body)\n}","typeGuard":"type checkoutResult struct {\n\tPath       string `json:\"path\"`\n\tBranchName string `json:\"branch_name\"`\n}\nfunc isCheckoutResult(v any) (checkoutResult, bool) {\n\tr, ok := v.(checkoutResult)\n\treturn r, ok && r.Path != \"\"\n}","tryCatchPattern":"if err := json.Unmarshal(body, &result); err != nil {\n\treturn fmt.Errorf(\"parse response: %w (raw: %.120s)\", err, body) // keep raw body for diagnosis\n}","preventionTips":["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."],"tags":["go","json","parsing","daemon","version-skew","port-collision"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}