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
- Unwrap the error (%w chain) to find the root cause from HandleRelay
- Increase the relay timeout configuration if the message was slow and the deadline fired
- Verify the target agent CLI is installed, authenticated, and healthy (run its doctor command)
- 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
- Set a realistic relay timeout in config (target agents can take minutes)
- Keep target agent CLIs installed and authenticated; run doctor regularly
- Unwrap %w chains with errors.Is/As instead of string matching
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
- get relay workspace agent: %w
- start relay session: %w
- send relay message: %w
- agent error (no details)
- acp: agent option "cmd" or "command" is required (path or na
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/fd478e7d3e43f480.
Report an issue: GitHub.