{"record":{"id":"61fe1ea175ed6fa9","repo":"multica-ai/multica","slug":"close-daemon-checkout-response-w","errorCode":null,"errorMessage":"close daemon checkout response: %w","messagePattern":"close daemon checkout response: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/cmd/multica/cmd_repo.go","lineNumber":394,"sourceCode":"\tcheckoutURL := fmt.Sprintf(\"http://127.0.0.1:%s/repo/checkout\", daemonPort)\n\tvar body []byte\n\tfor {\n\t\treq, err := http.NewRequestWithContext(ctx, http.MethodPost, checkoutURL, bytes.NewReader(data))\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"create daemon checkout request: %w\", err)\n\t\t}\n\t\treq.Header.Set(\"Content-Type\", \"application/json\")\n\t\tresp, err := client.Do(req)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"connect to daemon: %w\", err)\n\t\t}\n\t\tbody, err = io.ReadAll(resp.Body)\n\t\tcloseErr := resp.Body.Close()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"read daemon checkout response: %w\", err)\n\t\t}\n\t\tif closeErr != nil {\n\t\t\treturn fmt.Errorf(\"close daemon checkout response: %w\", closeErr)\n\t\t}\n\t\tif resp.StatusCode == http.StatusServiceUnavailable && resp.Header.Get(\"X-Multica-Retryable\") == \"repo-busy\" {\n\t\t\tdelay := repoCheckoutRetryDelay(resp.Header.Get(\"Retry-After\"), time.Now())\n\t\t\ttimer := time.NewTimer(delay)\n\t\t\tselect {\n\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","sourceCodeStart":376,"sourceCodeEnd":412,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/cmd/multica/cmd_repo.go#L376-L412","documentation":"runRepoCheckout checks resp.Body.Close() after reading and fails the command if closing returns an error. Close on an HTTP response body essentially only reports a prior unread-body error; since the body was fully read by io.ReadAll beforehand, this branch is defensive and near-unreachable — it would fire if the underlying connection was already in a broken state.","triggerScenarios":"The loopback connection was reset between ReadAll and Close, or a custom transport surfaced a deferred error on close; with the default transport and a fully-drained body this does not occur.","commonSituations":"None realistic in the current code path; would appear only under connection-level faults (sandbox tearing down sockets) racing the close call.","solutions":["Treat it like error 649: inspect daemon health/logs and retry the checkout.","If it recurs in a specific sandbox, check whether the network namespace/proxy kills idle sockets aggressively."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if closeErr := resp.Body.Close(); closeErr != nil {\n\t// body already drained; close errors here are informational\n\tlog.Printf(\"response close: %v\", closeErr)\n}","preventionTips":["Always drain the body (io.ReadAll) before Close — that is what this code already does.","Treat close-after-read errors as noise unless they recur with transport errors."],"tags":["go","http","resource-cleanup","unreachable","defensive-code"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}