openimsdk/open-im-server · warning
error (dynamic message passed to http.Error)
Error message
error (dynamic message passed to http.Error)
What it means
ErrReturn is a thin wrapper around net/http's http.Error, writing an error string and HTTP status code to the WebSocket upgrade response writer. Because the message is a dynamic string passed straight through, any caller-supplied text is emitted as the HTTP response body. This error entry flags that dynamic message: the client sees whatever string the gateway hands to ErrReturn (e.g. invalid token, bad upgrade request, rate limit).
Source
Thrown at internal/msggateway/context.go:193
info.SDKType = GoSDK
case GoSDK, JsSDK:
default:
return servererrs.ErrConnArgsErr.WrapMsg("sdkType is invalid")
}
c.info = info
return nil
}
func (c *UserConnContext) GetRemoteAddr() string {
return c.RemoteAddr
}
func (c *UserConnContext) SetHeader(key, value string) {
c.RespWriter.Header().Set(key, value)
}
func (c *UserConnContext) ErrReturn(error string, code int) {
http.Error(c.RespWriter, error, code)
}
func (c *UserConnContext) GetConnID() string {
return c.ConnID
}
func (c *UserConnContext) GetUserID() string {
if c == nil || c.info == nil {
return ""
}
return c.info.UserID
}
func (c *UserConnContext) GetPlatformID() int {
if c == nil || c.info == nil {
return 0
}
return c.info.PlatformIDView on GitHub (pinned to 175a7bb067)
Solutions
- Inspect the HTTP response body/status returned on the WS handshake — the dynamic string is the gateway's rejection reason; fix the underlying condition it reports (usually token or params).
- In the gateway, replace free-form strings with typed, constant error messages so clients can match them reliably.
- Ensure ErrReturn is only called with non-sensitive, user-safe messages; log full details server-side instead.
- Client-side: handle non-101 handshake responses explicitly (check response status/code) rather than treating any failure as a network error.
Example fix
// before
c.ErrReturn(fmt.Sprintf("token invalid: %v", err), http.StatusUnauthorized)
// after
c.ErrReturn("token invalid", http.StatusUnauthorized) // details logged server-side Defensive patterns
Strategy: try-catch
Validate before calling
// client-side, before treating handshake as success
resp, err := dialer.DialContext(ctx, wsURL, hdr)
if err != nil {
if resp != nil && resp.StatusCode != http.StatusSwitchingProtocols {
body, _ := io.ReadAll(io.LimitReader(resp.Body, 512))
return fmt.Errorf("gateway rejected handshake (%d): %s", resp.StatusCode, body)
}
return err
} Type guard
func isGatewayRejection(err error) bool {
var he *websocket.HTTPError // or check resp status from your WS lib
return errors.As(err, &he) && he.StatusCode >= 400
} Try / catch
conn, resp, err := dialer.Dial(wsURL, hdr)
if err != nil {
if resp != nil {
switch resp.StatusCode {
case http.StatusUnauthorized:
// refresh token and retry once
case http.StatusForbidden:
// origin/permission problem — do not retry
default:
log.Printf("gateway error: %s", resp.Status)
}
}
return err
} Prevention
- Always check the HTTP status of a failed WS handshake before retrying; the dynamic message explains the rejection.
- Refresh credentials proactively so token-expiry rejections (the most common ErrReturn path) are rare.
- Match on status code, not on the error string — gateway messages are dynamic and may change between versions.
- Server-side: restrict ErrReturn inputs to a fixed set of constant messages to keep client handling stable.
When it happens
Trigger: Any code path in the message gateway that calls UserConnContext.ErrReturn(msg, code) before or instead of upgrading the WebSocket connection — e.g. failed authentication/token validation, missing query parameters, rejected origin, or internal errors during the HTTP handshake phase.
Common situations: A client hits the WebSocket endpoint with an expired/invalid token and receives a plain-text error body instead of a WS connection; proxy or CORS misconfig causes the handshake to be rejected; gateway version changes the error strings so client-side parsers break; developers accidentally send sensitive internals via this dynamic message.
Related errors
AI-assisted analysis of openimsdk/open-im-server@175a7bb067 (2026-09-04).
Data as JSON: /api/errors/947b426408a69308.
Report an issue: GitHub.