hashicorp/nomad · error
tty value is not a boolean: %v
Error message
tty value is not a boolean: %v
What it means
jobRunAction (command/agent/job_endpoint.go:388), reached via JobSpecificRequest for the exec/stream job actions, reads the ?tty= query parameter and parses it with strconv.ParseBool. If the value is non-empty and not a valid Go boolean literal, the request fails with 'tty value is not a boolean'. This rejects the exec request before an allocation is targeted, so no process is started.
Source
Thrown at command/agent/job_endpoint.go:388
}
setMeta(resp, &structs.QueryMeta{})
return out.Actions, nil
}
func (s *HTTPServer) jobRunAction(resp http.ResponseWriter, req *http.Request, jobID string) (any, error) {
task := req.URL.Query().Get("task")
action := req.URL.Query().Get("action")
allocID := req.URL.Query().Get("allocID")
// Build the request and parse the ACL token
var err error
isTTY := false
if tty := req.URL.Query().Get("tty"); tty != "" {
isTTY, err = strconv.ParseBool(tty)
if err != nil {
return nil, fmt.Errorf("tty value is not a boolean: %v", err)
}
}
args := cstructs.AllocExecRequest{
JobID: jobID,
Task: task,
Action: action,
AllocID: allocID,
Tty: isTTY,
}
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
- Set the query parameter to a valid boolean literal: tty=true or tty=false (1/0, t/f also accepted).
- Omit the tty parameter entirely when not needed; empty/missing means non-TTY (isTTY=false).
- Inspect the %v value in the error to see exactly what string was received and correct the client.
- If building requests programmatically, encode the value with strconv.FormatBool(isTTY).
Example fix
// before
url := fmt.Sprintf("/v1/job/%s/exec?task=%s&tty=%s", jobID, task, "yes")
// after
url := fmt.Sprintf("/v1/job/%s/exec?task=%s&tty=%s", jobID, task, strconv.FormatBool(true)) Defensive patterns
Strategy: validation
Validate before calling
// Before issuing the job exec request
ttyStr := strconv.FormatBool(isTTY)
if _, err := strconv.ParseBool(ttyStr); err != nil {
return fmt.Errorf("refusing to send invalid tty param %q", ttyStr)
}
url := fmt.Sprintf("...?task=%s&tty=%s", task, ttyStr) Type guard
func isValidTTYParam(s string) bool {
return s == "true" || s == "false"
} Try / catch
resp, err := http.Post(execURL+"?tty="+ttyStr, "", body)
if err != nil { return err }
if resp.StatusCode == 400 {
// 'tty value is not a boolean' — re-send without the tty param
return retryWithoutTTY(execURL, body)
} Prevention
- Build the tty param with strconv.FormatBool, never string interpolation of arbitrary flags.
- Use a real bool type in CLI/config plumbing all the way to the URL.
- Omit ?tty instead of sending an empty value.
- Test exec commands with both tty=true and tty=false once per wrapper script.
When it happens
Trigger: GET/POST to the Nomad job exec endpoint (e.g. /v1/client/allocation/... or job exec webSocket route) with ?tty=<bad value> such as tty=yes, tty=on, tty=1.0, or an unexpanded variable. Any non-empty value other than 1/t/T/TRUE/true/True/0/f/F/FALSE/false/False triggers this.
Common situations: Hand-rolled websocket/curl commands for nomad alloc exec equivalents using 'yes'/'no'; UI or scripting wrappers passing string flags; query strings built by concatenation where a config variable contains an unexpected string; users copying '?tty=1' typo'd as '?tty=1x'.
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.
Related errors
- Failed to parse value of %q (%v) as a bool: %v
- Failed to parse value of %qq (%v) as a bool: %v
- Failed to parse value of %q (%v) as a bool: %v
- Failed to parse value of %q (%v) as a int: %v
- Failed to parse value of %q (%v) as a uint64: %v
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/dbeb79c9f5aed647.
Report an issue: GitHub.