hashicorp/nomad · error
tty value is not a boolean: %v
Error message
tty value is not a boolean: %v
What it means
This error is raised by allocExec in command/agent/alloc_endpoint.go:604 when the `tty` query parameter of the exec endpoint is present but strconv.ParseBool cannot parse it. ParseBool only accepts 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False, so any other value (e.g. "yes", "on", "1 " with whitespace, or an empty-but-present parameter after intermediary rewriting) fails.
Source
Thrown at command/agent/alloc_endpoint.go:604
return reply.Results, rpcErr
}
func (s *HTTPServer) allocExec(allocID string, resp http.ResponseWriter, req *http.Request) (any, error) {
// Build the request and parse the ACL token
task := req.URL.Query().Get("task")
cmdJsonStr := req.URL.Query().Get("command")
var command []string
err := json.Unmarshal([]byte(cmdJsonStr), &command)
if err != nil {
// this shouldn't happen, []string is always be serializable to json
return nil, fmt.Errorf("failed to marshal command into json: %v", err)
}
ttyB := false
if tty := req.URL.Query().Get("tty"); tty != "" {
ttyB, err = strconv.ParseBool(tty)
if err != nil {
return nil, fmt.Errorf("tty value is not a boolean: %v", err)
}
}
args := cstructs.AllocExecRequest{
AllocID: allocID,
Task: task,
Cmd: command,
Tty: ttyB,
}
s.parse(resp, req, &args.QueryOptions.Region, &args.QueryOptions)
conn, err := s.getWebsocketConnection(req)
if err != nil {
return nil, err
}
return s.execStream(conn, &args)
}View on GitHub (pinned to 482b49bf1a)
Solutions
- Send only values strconv.ParseBool accepts: true/false, 1/0, t/f, T/F, TRUE/FALSE, True/False.
- Coerce your client's boolean to a canonical 'true'/'false' string before building the query string.
- Omit the tty parameter entirely when no TTY is desired (absence defaults to false).
- Check for accidental whitespace or duplicated parameters (tty=true&tty=yes) in the URL.
Example fix
// before: shell-style boolean
url := fmt.Sprintf(".../exec?allocID=%s&task=%s&command=%s&tty=%v", allocID, task, cmd, "yes")
// after: canonical bool string
url := fmt.Sprintf(".../exec?allocID=%s&task=%s&command=%s&tty=%t", allocID, task, cmd, wantTTY) Defensive patterns
Strategy: validation
Validate before calling
if _, err := strconv.ParseBool(ttyParam); err != nil {
return fmt.Errorf("tty must be a ParseBool-compatible bool, got %q", ttyParam)
} Type guard
func isParseBool(s string) bool {
_, err := strconv.ParseBool(s)
return err == nil
} Prevention
- Serialize booleans with %t or strconv.FormatBool, never shell-style yes/no strings.
- Omit the tty parameter when false; only append it when TTY is requested.
- Sanitize inputs for stray whitespace before placing them in query strings.
- Remember only 1/0, t/f, true/false (and case variants) are accepted by Go's strconv.ParseBool.
When it happens
Trigger: Calling GET /v1/client/allocation/<allocID>/exec with a non-empty `tty` query parameter that is not a Go-recognized boolean literal — e.g. tty=yes, tty=on, tty=2, or tty=%20 (whitespace).
Common situations: Tooling using shell-style yes/no flags against the Nomad HTTP API; URL builders appending tty with a formatted non-bool value; hand-written clients assuming a wider accepted boolean set than ParseBool supports.
Related errors
- failed to marshal command into json: %v
- no exec command is configured
- unknown task name %q
- task %q not started yet.
- task %q is not running.
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/726b4eebe7c03ed0.
Report an issue: GitHub.