multica-ai/multica · warning

encode request: %w

Error message

encode request: %w

What it means

runRepoCheckout wraps json.Marshal(reqBody) where reqBody is a map[string]any built only from strings, an int-shaped bool literal, and strings.TrimSpace results. Marshaling a map of primitive values cannot fail in practice — all values (strings and the bool true) are marshal-safe — so this error is effectively unreachable defensive code.

Source

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

	workDir, err := os.Getwd()
	if err != nil {
		return fmt.Errorf("get working directory: %w", err)
	}

	reqBody := map[string]any{
		"url":           repoURL,
		"workspace_id":  workspaceID,
		"workdir":       workDir,
		"ref":           repoCheckoutRef,
		"agent_name":    agentName,
		"task_id":       taskID,
		"checkout_mode": strings.TrimSpace(os.Getenv("MULTICA_REPO_CHECKOUT_MODE")),
		"retry_busy":    true,
	}

	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)

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. If you genuinely hit this in a modified build, inspect reqBody for non-serializable values (channels/functions) added by your patch.
  2. For maintainers: values are all string/bool, so this branch can be simplified or asserted away.
Defensive patterns

Strategy: type-guard

Type guard

// guard the map before marshal if extending reqBody
func marshalSafe(v any) bool {
	switch v.(type) {
	case string, bool, int, int64, float64, nil:
		return true
	}
	return false
}
for _, v := range reqBody {
	if !marshalSafe(v) { return fmt.Errorf("non-serializable field in request body") }
}

Prevention

When it happens

Trigger: Theoretically only if reqBody ever gained a channel, function, or complex value in a future edit; with the current body ({url, workspace_id, workdir, ref, agent_name, task_id, checkout_mode, retry_busy:true}) it cannot trigger.

Common situations: None in the current code; would appear only after someone adds a non-marshalable value (chan, func, complex, or a struct with unsupported fields) to reqBody.

Related errors


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