chenhg5/cc-connect · error

acp: session/new: empty sessionId

Error message

acp: session/new: empty sessionId

What it means

Raised when the `session/new` call succeeded and parsed, but the returned sessionId field is empty. An ACP session without an id is unusable (session/prompt needs it), so the handshake is treated as failed.

Source

Thrown at agent/acp/session.go:246

	}

	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()
	s.availableModes = append(s.availableModes[:0], block.AvailableModes...)
	if block.CurrentModeID != "" {
		s.currentMode = block.CurrentModeID

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Upgrade the agent to a version with a conforming session/new implementation.
  2. Check agent logs/stderr for an internal error that made it return an empty id.
  3. Test the agent directly with an ACP client (e.g. Zed) to confirm it returns a real sessionId.
  4. If a wrapper/shim produces the response, fix it to propagate the agent's actual session id.

Example fix

// non-conforming agent response
// {"sessionId": ""}
// after: agent returns
// {"sessionId": "sess_01H...", "modes": {"currentModeId": "code"}}
Defensive patterns

Strategy: validation

Validate before calling

var probe struct{ SessionID string `json:"sessionId"` }
if err := json.Unmarshal(newRes, &probe); err == nil && probe.SessionID == "" {
    return fmt.Errorf("agent returned empty sessionId")
}

Try / catch

sess, err := agent.StartSession(ctx, id, nil)
if err != nil && strings.Contains(err.Error(), "empty sessionId") {
    slog.Error("agent violates ACP session/new contract — upgrade agent", "err", err)
    return err
}

Prevention

When it happens

Trigger: The agent's session/new result contains no `sessionId` key or an empty string value — typically a non-conforming agent or a server that reports success while failing to actually create the session.

Common situations: Agent bug or incomplete ACP implementation returning an empty id; a shim returning {"sessionId": ""} on internal error; version mismatch where the agent creates sessions lazily and does not return ids.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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