multica-ai/multica · error

create daemon checkout request: %w

Error message

create daemon checkout request: %w

What it means

runRepoCheckout wraps the error from http.NewRequestWithContext for POST http://127.0.0.1:{MULTICA_DAEMON_PORT}/repo/checkout. NewRequestWithContext fails only for a malformed method or an unparseable URL. Since the method is constant and the host is fixed to 127.0.0.1, this fires only when MULTICA_DAEMON_PORT holds characters that break URL parsing (letters, whitespace, brackets).

Source

Thrown at server/cmd/multica/cmd_repo.go:381

	data, err := json.Marshal(reqBody)
	if err != nil {
		return fmt.Errorf("encode request: %w", err)
	}

	parentCtx := cmd.Context()
	if parentCtx == nil {
		parentCtx = context.Background()
	}
	ctx, cancel := context.WithTimeout(parentCtx, 5*time.Minute)
	defer cancel()
	client := &http.Client{}
	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 {

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Print the variable and strip junk: echo "[$MULTICA_DAEMON_PORT]"; re-export a clean numeric value.
  2. Validate in shell before running: case "$MULTICA_DAEMON_PORT" in ''|*[!0-9]*) echo "bad port"; exit 1;; esac.
  3. If the value comes from an env file, convert line endings (dos2unix) or quote it correctly.

Example fix

# before
export MULTICA_DAEMON_PORT="8080 "   # trailing space -> invalid URL

# after
export MULTICA_DAEMON_PORT=8080
multica repo checkout https://github.com/acme/api
Defensive patterns

Strategy: validation

Validate before calling

port := os.Getenv("MULTICA_DAEMON_PORT")
if n, err := strconv.Atoi(strings.TrimSpace(port)); err != nil || n < 1 || n > 65535 {
	return fmt.Errorf("MULTICA_DAEMON_PORT=%q is not a valid port", port)
}

Prevention

When it happens

Trigger: MULTICA_DAEMON_PORT set to a non-numeric value, e.g. "8080 " (trailing whitespace), "http" or "8_080", making "http://127.0.0.1:8_080/repo/checkout" invalid.

Common situations: Manually exporting MULTICA_DAEMON_PORT with a typo when testing outside the daemon; env files with CRLF line endings appending \r to the value; templates injecting a unit like "8080tcp".

Related errors


AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15). Data as JSON: /api/errors/edd0fa11545eaec9. Report an issue: GitHub.