hashicorp/nomad · error
invalid websocket connection in context
Error message
invalid websocket connection in context
What it means
Type-guard failure in getWebsocketConnection: the request context lacks a *websocket.Conn under ctxKeyWebSocketConn (the value is missing or of the wrong type), meaning the audit wrapper did not attach an upgraded connection; callers allocExec/jobRunAction then abort.
Source
Thrown at command/agent/websockets.go:184
if h.Version != supportedWSHandshakeVersion {
return "", fmt.Errorf("unexpected handshake value: %v", h.Version)
}
return h.AuthToken, nil
}
// getWebsocketConnection retrieves the websocket connection from context
func (s *HTTPServer) getWebsocketConnection(req *http.Request) (*websocket.Conn, error) {
ctx := req.Context()
// Get websocket connection from context (set by audit wrapper)
connRaw := ctx.Value(ctxKeyWebSocketConn)
if connRaw == nil {
return nil, fmt.Errorf("websocket connection not found in context")
}
conn, ok := connRaw.(*websocket.Conn)
if !ok {
return nil, fmt.Errorf("invalid websocket connection in context")
}
return conn, nil
}
// runWebsocketWatcher reads messages from a websocket using the watcher
// protocol. That usage does not read from the websocket, but reads are
// required to receive control messages so this will continually read
// the websocket until an error is encountered.
func (s *HTTPServer) runWebsocketWatcher(conn *websocket.Conn) {
for {
if _, _, err := conn.ReadMessage(); err != nil {
s.logger.Trace("watcher websocket reader encountered error, stopping read", "error", err)
return
}
}
}
View on GitHub (pinned to 482b49bf1a)
Solutions
- Fix the middleware responsible so it stores a *websocket.Conn under ctxKeyWebSocketConn.
- Audit all uses of ctxKeyWebSocketConn for key collisions and consolidate on one setter.
- Update tests/mocks to inject an actual *websocket.Conn (or the shared key with correct type).
- Re-run against stock Nomad to rule out a fork/patched binary storing a wrong type.
Example fix
// before ctx = context.WithValue(ctx, ctxKeyWebSocketConn, myConnWrapper) // after ctx = context.WithValue(ctx, ctxKeyWebSocketConn, wsConn) // *websocket.Conn
Defensive patterns
Strategy: type-guard
Validate before calling
connRaw := ctx.Value(ctxKeyWebSocketConn)
conn, ok := connRaw.(*websocket.Conn)
if !ok {
return nil, fmt.Errorf("invalid websocket connection in context: %T", connRaw)
} Try / catch
conn, err := s.getWebsocketConnection(req)
if err != nil {
log.Printf("ws context corruption (check middleware types): %v", err)
return err
} Prevention
- Use a single unexported key type for ctxKeyWebSocketConn.
- Never store wrapper/mock types under that key.
- Review custom middleware for context key collisions.
- Include %T in error logs to identify the offending type fast.
When it happens
Trigger: getWebsocketConnection (called by allocExec/jobRunAction) finds ctx.Value(ctxKeyWebSocketConn) non-nil but of a different concrete type — caused by another middleware storing a conflicting value under the same key or a refactor changing the stored type.
Common situations: Two wrappers using the same context key for different purposes; custom middleware patched in; tests injecting a mock connection of the wrong type into the request context.
Related errors
- error executing protected function %w
- ws_handshake value is not a boolean: %v
- invalid digest format
- unsupported checksum format
- must pass non-nil job
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/6f6f3d717dbd8d30.
Report an issue: GitHub.