multica-ai/multica · warning
close daemon checkout response: %w
Error message
close daemon checkout response: %w
What it means
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.
Source
Thrown at server/cmd/multica/cmd_repo.go:394
checkoutURL := fmt.Sprintf("http://127.0.0.1:%s/repo/checkout", daemonPort)
var body []byte
for {
req, err := http.NewRequestWithContext(ctx, http.MethodPost, checkoutURL, bytes.NewReader(data))
if err != nil {
return fmt.Errorf("create daemon checkout request: %w", err)
}
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("connect to daemon: %w", err)
}
body, err = io.ReadAll(resp.Body)
closeErr := resp.Body.Close()
if err != nil {
return fmt.Errorf("read daemon checkout response: %w", err)
}
if closeErr != nil {
return fmt.Errorf("close daemon checkout response: %w", closeErr)
}
if resp.StatusCode == http.StatusServiceUnavailable && resp.Header.Get("X-Multica-Retryable") == "repo-busy" {
delay := repoCheckoutRetryDelay(resp.Header.Get("Retry-After"), time.Now())
timer := time.NewTimer(delay)
select {
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
}
View on GitHub (pinned to 2c0912b6ec)
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.
Defensive patterns
Strategy: try-catch
Try / catch
if closeErr := resp.Body.Close(); closeErr != nil {
// body already drained; close errors here are informational
log.Printf("response close: %v", closeErr)
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: None realistic in the current code path; would appear only under connection-level faults (sandbox tearing down sockets) racing the close call.
Related errors
AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15).
Data as JSON: /api/errors/61fe1ea175ed6fa9.
Report an issue: GitHub.