chenhg5/cc-connect · error

relay: %w

Error message

relay: %w

What it means

Wrap-around error from RelayManager.Send: the target engine's HandleRelay call returned an error, which Send re-wraps with the 'relay:' prefix. The root cause is inside the target engine's relay handling (session creation, message injection, agent process failure, or the relay context timeout expiring).

Source

Thrown at core/relay.go:259

	}

	// Post the forwarded message to the group chat for visibility.  The
	// default target is "<platform>:<chatID>:relay"; platforms that
	// understand thread / topic semantics can override this by
	// implementing core.RelayGroupVisibilityTarget on their Platform impl.
	groupSessionKey := rm.resolveGroupVisibilityKey(platform, chatID, req.SessionKey, sourceEngine)
	if sourceEngine != nil && visibility != RelayVisibilityNone {
		label := relayVisibilityRequestLabel(visibility, fromName, toName, req.Message)
		rm.sendToGroup(ctx, sourceEngine, platform, groupSessionKey, label)
	}

	// Execute relay: inject message into target engine and collect response
	relayCtx, cancel := rm.relayContext(ctx)
	defer cancel()

	response, err := targetEngine.HandleRelay(relayCtx, req.From, req.SessionKey, req.Message)
	if err != nil {
		return nil, fmt.Errorf("relay: %w", err)
	}

	// Post the response to the group chat for visibility.
	if targetEngine != nil && visibility != RelayVisibilityNone {
		label := relayVisibilityResponseLabel(visibility, toName, response)
		rm.sendToGroup(ctx, targetEngine, platform, groupSessionKey, label)
	}

	return &RelayResponse{Response: response}, nil
}

// sendToGroup sends a message to the group chat for visibility.
func (rm *RelayManager) sendToGroup(ctx context.Context, e *Engine, platform, sessionKey, content string) {
	for _, p := range e.platforms {
		if p.Name() != platform {
			continue
		}
		rc, ok := p.(ReplyContextReconstructor)

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Unwrap the error (%w chain) to find the root cause from HandleRelay
  2. Increase the relay timeout configuration if the message was slow and the deadline fired
  3. Verify the target agent CLI is installed, authenticated, and healthy (run its doctor command)
  4. Inspect the target engine's logs at the time of the relay for the underlying failure

Example fix

// before: opaque handling
resp, err := rm.Send(ctx, req)
if err != nil { log.Print(err) } // "relay: context deadline exceeded"
// after: unwrap to the root cause
if err != nil { log.Printf("relay root cause: %v", errors.Unwrap(err)) }
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check what HandleRelay depends on
if rm.RelayTimeout() > 0 && rm.RelayTimeout() < 30*time.Second { log.Warn("relay timeout very low") }
if err := targetAgent.HealthCheck(ctx); err != nil { return fmt.Errorf("target agent unhealthy: %w", err) }

Try / catch

resp, err := rm.Send(ctx, req)
if err != nil {
	if errors.Is(err, context.DeadlineExceeded) {
		reply("Relay timed out; try again or increase the relay timeout.")
		return
	}
	reply("Relay failed: " + errors.Unwrap(err).Error())
	return
}

Prevention

When it happens

Trigger: targetEngine.HandleRelay(relayCtx, ...) returns any error: agent process failed to start, the target session errored, the relay timeout (rm.timeout) elapsed and cancelled relayCtx, or the target agent rejected the message.

Common situations: Relay timeout too short for a slow agent response; target agent CLI not installed or failing auth; target session in a bad state; context cancellation propagated from an upstream user cancel.

Related errors


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