hashicorp/nomad · error
ws_handshake value is not a boolean
Error message
ws_handshake value is not a boolean: %v
What it means
readWsHandshake parses the ws_handshake query parameter as a boolean to decide whether a websocket handshake message is required. This error is returned when the parameter is present but strconv.ParseBool cannot parse it, so the request is malformed before any upgrade.
Solutions
- Send ws_handshake=true or ws_handshake=false (or 1/0, t/f) — exactly the literals strconv.ParseBool accepts.
- Omit the ws_handshake parameter entirely when no handshake is needed (empty means skip).
- Fix the client code constructing the URL to pass a real boolean, not a string.
- Update wrapper scripts/SDKs that interpolate malformed query values.
Example fix
// before url := base + "/exec?ws_handshake=yes" // after url := base + "/exec?ws_handshake=true"
Defensive patterns
Strategy: validation
Validate before calling
hv := req.URL.Query().Get("ws_handshake")
if hv != "" {
if _, err := strconv.ParseBool(hv); err != nil {
http.Error(w, "ws_handshake must be a boolean", http.StatusBadRequest)
return
}
} Try / catch
if _, err := strconv.ParseBool(hv); err != nil {
http.Error(w, fmt.Sprintf("ws_handshake value is not a boolean: %v", err), http.StatusBadRequest)
return
} Prevention
- Always serialize booleans with strconv.FormatBool when building URLs.
- Validate query params on the client before dispatching the request.
- Keep SDK/wrapper templates typed (bool), not string-interpolated.
- Document accepted literals (true/false/1/0/t/f).
When it happens
Trigger: Client hits a websocket endpoint with e.g. ?ws_handshake=yes or ?ws_handshake=1.0 — any value outside strconv.ParseBool's accepted set (1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False).
Common situations: Hand-rolled websocket clients or templates interpolating strings into the query string; proxies rewriting boolean query values; users typing 'yes'/'on' by intuition.
Understand the failure class
Background: "Invalid query parameter" / "Failed to parse value of ...": fixing bad query string parameters across APIs — this error's family across 36 libraries.
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- A template must be supplied using '-template' when using…
- A template must be supplied using '-template' when using…
- ExternalID is required
- format flag required
- fuzzy search query must be at least
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/ac3882fab84e4f88.
Report an issue: GitHub.
Appendix: source
Thrown at command/agent/websockets.go:145
conn.WriteMessage(websocket.CloseMessage,
websocket.FormatCloseMessage(websocket.CloseNormalClosure, "request complete"))
return nil, nil
}
}
type wsHandshakeMessage struct {
Version int `json:"version"`
AuthToken string `json:"auth_token"`
}
// readWsHandshake reads the websocket handshake message and returns the auth token
func (s *HTTPServer) readWsHandshake(readFn func(any) error, req *http.Request) (string, error) {
// Avoid handshake if request doesn't require one
if hv := req.URL.Query().Get("ws_handshake"); hv == "" {
return "", nil
} else if h, err := strconv.ParseBool(hv); err != nil {
return "", fmt.Errorf("ws_handshake value is not a boolean: %v", err)
} else if !h {
return "", nil
}
// verify that any header token set by a non-browser client agrees with the
// auth header
reqToken := new(string)
s.parseToken(req, reqToken)
var h wsHandshakeMessage
err := readFn(&h)
if err != nil {
return "", err
}
if reqToken != nil && *reqToken != "" && *reqToken != h.AuthToken {
return "", fmt.Errorf("handshake auth token mismatched auth header token")
}View on GitHub (pinned to 482b49bf1a)