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

  1. Check both ends of the relay run the same CLIProxyAPI version so error payloads are always populated.
  2. Capture the raw relay frames (wsrelay debug logging) to see what the peer actually sent before the nil payload.
  3. Treat this error as a signal to inspect the peer's logs — the real failure happened on the other side and was not serialized.
  4. 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

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


AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15). Data as JSON: /api/errors/fa7d1cca62058a0a. Report an issue: GitHub.