router-for-me/CLIProxyAPI · warning
wsrelay: unknown error
Error message
wsrelay: unknown error
What it means
decodeError in internal/wsrelay/http.go decodes an error frame (MessageTypeError) from the relay peer. If the payload map is nil — i.e. an error message arrived with no payload — it returns the generic `wsrelay: unknown error`. It is a defensive fallback for malformed/empty error frames; any real error should carry an `error` string and `status` number, which get formatted as `"%s (status=%d)"`.
Source
Thrown at internal/wsrelay/http.go:237
if body, ok := payload["body"].(string); ok {
resp.Body = []byte(body)
}
return resp
}
func decodeChunk(payload map[string]any) []byte {
if payload == nil {
return nil
}
if data, ok := payload["data"].(string); ok {
return []byte(data)
}
return nil
}
func decodeError(payload map[string]any) error {
if payload == nil {
return errors.New("wsrelay: unknown error")
}
message, _ := payload["error"].(string)
status := 0
if v, ok := payload["status"].(float64); ok {
status = int(v)
}
if message == "" {
message = "wsrelay: upstream error"
}
return fmt.Errorf("%s (status=%d)", message, status)
}
View on GitHub (pinned to 78f0c4079e)
Solutions
- Check both ends of the relay run the same CLIProxyAPI version so error payloads are always populated.
- Capture the raw relay frames (wsrelay debug logging) to see what the peer actually sent before the nil payload.
- Treat this error as a signal to inspect the peer's logs — the real failure happened on the other side and was not serialized.
- Report upstream if the peer is a current CLIProxyAPI build, since error frames should always carry payload.
Defensive patterns
Strategy: fallback
Type guard
func isUnknownRelayError(err error) bool {
return err != nil && strings.Contains(err.Error(), "wsrelay: unknown error")
} Try / catch
if isUnknownRelayError(err) {
// real cause lives on the peer: check peer logs; retry once in case of frame corruption
log.Warn("relay error frame had no payload; inspecting peer")
err = retryOnce()
} Prevention
- Pin both ends of the relay to the same CLIProxyAPI version.
- Log raw relay frames in debug mode so empty error payloads are diagnosable.
- Always populate error payloads when implementing a relay peer.
When it happens
Trigger: The relay peer sends a MessageTypeError frame with a nil or absent payload; version skew between proxy and relay peer where one side encodes errors differently; internal bug producing an error frame without payload.
Common situations: Mismatched CLIProxyAPI versions on either end of the wsrelay; a peer implementation that sends `{type:"error"}` with no details; debugging sessions where the actual cause is hidden by the generic message.
Related errors
- wsrelay: connection closed during response
- wsrelay: stream closed
- decode Claude OAuth response: unsupported content encoding %
- home certificate request returned nil
- %s
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/fa7d1cca62058a0a.
Report an issue: GitHub.