hashicorp/nomad · warning
must provide log type (stdout/stderr)
Error message
must provide log type (stdout/stderr)
What it means
logTypeNotPresentErr is a sentinel error for log requests whose Type is neither "stdout" nor "stderr". The client maps this field onto a filename variant, so anything else is rejected. Returned with HTTP 400 Bad Request from the logs endpoints.
Source
Thrown at client/fs_endpoint.go:36
"syscall"
"time"
metrics "github.com/hashicorp/go-metrics/compat"
"github.com/hashicorp/go-msgpack/v2/codec"
"github.com/hpcloud/tail/watch"
"github.com/hashicorp/nomad/acl"
"github.com/hashicorp/nomad/client/allocdir"
sframer "github.com/hashicorp/nomad/client/lib/streamframer"
cstructs "github.com/hashicorp/nomad/client/structs"
"github.com/hashicorp/nomad/nomad/structs"
)
var (
allocIDNotPresentErr = fmt.Errorf("must provide a valid alloc id")
pathNotPresentErr = fmt.Errorf("must provide a file path")
taskNotPresentErr = fmt.Errorf("must provide task name")
logTypeNotPresentErr = fmt.Errorf("must provide log type (stdout/stderr)")
invalidOrigin = fmt.Errorf("origin must be start or end")
)
const (
// streamFramesBuffer is the number of stream frames that will be buffered
// before back pressure is applied on the stream framer.
streamFramesBuffer = 32
// streamFrameSize is the maximum number of bytes to send in a single frame
streamFrameSize = 64 * 1024
// streamHeartbeatRate is the rate at which a heartbeat will occur to detect
// a closed connection without sending any additional data
streamHeartbeatRate = 1 * time.Second
// streamBatchWindow is the window in which file content is batched before
// being flushed if the frame size has not been hit.
streamBatchWindow = 200 * time.MillisecondView on GitHub (pinned to 482b49bf1a)
Solutions
- Set the type parameter to exactly "stdout" or "stderr" (lowercase)
- In code, normalize/validate the log type before the request: switch t { case "stdout", "stderr": ... default: reject }
- If you need both streams, issue two requests rather than a combined value
Example fix
// before
req := &cstructs.FsLogsRequest{AllocID: id, Task: "web", Type: "out"}
// after
req := &cstructs.FsLogsRequest{AllocID: id, Task: "web", Type: "stdout"} Defensive patterns
Strategy: validation
Validate before calling
switch logType {
case "stdout", "stderr":
// ok
default:
return fmt.Errorf("log type must be exactly \"stdout\" or \"stderr\", got %q", logType)
} Type guard
func isValidLogType(t string) bool {
return t == "stdout" || t == "stderr"
} Try / catch
r, err := client.AllocFS().Logs(alloc, task, "", false, logType, "end", 0, ctx.Done(), nil)
if err != nil && strings.Contains(err.Error(), "must provide log type") {
log.Printf("bad log type %q, falling back to stdout", logType)
return client.AllocFS().Logs(alloc, task, "", false, "stdout", "end", 0, ctx.Done(), nil)
} Prevention
- Whitelist the two valid values at the CLI/UI layer instead of free-text input
- Normalize case (strings.ToLower) before sending
- Never use numeric fd labels or abbreviations; use the API's exact strings
When it happens
Trigger: Calling logs/Logs with a req.Type value outside {"stdout", "stderr"} — empty string, "out", "1", "both", etc.
Common situations: CLI/API callers using abbreviations like 'out' or numeric fd identifiers; template variables defaulting to empty; mixing up the parameter name (passing log level or file name where type is expected).
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- must provide task name
- origin must be start or end
- missing policy name
- Unknown log level
- command is not present
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/e2df5bab80ddff9b.
Report an issue: GitHub.