chenhg5/cc-connect · error

acp: parse session/new: %w

Error message

acp: parse session/new: %w

What it means

Wrapped when the `session/new` JSON-RPC result cannot be unmarshalled into the expected shape ({sessionId, modes}). The agent answered session/new but the payload is malformed, so no session id can be cached and the handshake fails.

Source

Thrown at agent/acp/session.go:243

				return nil
			}
		}
	}

	newParams := map[string]any{
		"cwd":        s.workDir,
		"mcpServers": []any{},
	}
	newRes, err := s.tr.call(s.ctx, "session/new", newParams)
	if err != nil {
		return fmt.Errorf("acp: session/new: %w", err)
	}
	var sn struct {
		SessionID string         `json:"sessionId"`
		Modes     *acpModesBlock `json:"modes"`
	}
	if err := json.Unmarshal(newRes, &sn); err != nil {
		return fmt.Errorf("acp: parse session/new: %w", err)
	}
	if sn.SessionID == "" {
		return fmt.Errorf("acp: session/new: empty sessionId")
	}
	s.setACPSessionID(sn.SessionID)
	s.absorbModes(sn.Modes)
	return nil
}

// absorbModes copies a modes block into the session's cache and fans
// it out to the parent agent callbacks (if any). Both the session and
// the agent need the information: the session uses it to validate
// SetLiveMode inputs; the agent uses it to render `/mode` menus in IM.
func (s *acpSession) absorbModes(block *acpModesBlock) {
	if block == nil || len(block.AvailableModes) == 0 {
		return
	}
	s.modesMu.Lock()

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Dump the raw newRes payload to compare against the expected {sessionId, modes} schema.
  2. Upgrade the agent (or cc-connect) so both sides use the same ACP schema version.
  3. If the agent uses a different field name for the session id, wrap/normalize the response in the transport before unmarshal.
  4. Remove any proxy/transform layer between cc-connect and the agent that could alter the JSON.

Example fix

// agent replying {"id": "s_1"} instead of {"sessionId": "s_1"}
// after: use an agent build that returns {"sessionId": "s_1", "modes": {...}}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-validate session/new response shape before trusting it
var probe struct{ SessionID string `json:"sessionId"` }
if err := json.Unmarshal(newRes, &probe); err != nil {
    return fmt.Errorf("agent session/new payload non-conforming")
}

Try / catch

sess, err := agent.StartSession(ctx, id, nil)
if err != nil && strings.Contains(err.Error(), "parse session/new") {
    slog.Error("agent session/new schema mismatch — likely version skew", "err", err)
    return err
}

Prevention

When it happens

Trigger: The agent's session/new result is not the expected JSON object — missing/mis-typed `sessionId`, wrong field names (e.g. `id` instead of `sessionId`), or non-JSON body — causing json.Unmarshal to fail.

Common situations: Agent speaks a divergent ACP dialect with different field casing/names; a middleware rewrites or truncates the response; agent version skew with the client's expected schema.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/23d6af6378f8875e. Report an issue: GitHub.