hashicorp/nomad · warning

origin must be start or end

Error message

origin must be start or end

What it means

invalidOrigin is a sentinel error for file-stream and log requests whose Origin field is not "start" or "end". Origin controls whether streaming begins at the beginning of the file or at the end (follow mode). Invalid values are rejected with HTTP 400 before any file access.

Source

Thrown at client/fs_endpoint.go:37

	"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.Millisecond

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Use only "start" or "end" (lowercase) for the origin parameter, or omit it entirely to get the default
  2. For tail/follow behavior use origin=end; for full history use origin=start
  3. Validate/normalize the value in your client before sending: strings.ToLower + whitelist check

Example fix

// before
GET /v1/client/fs/logs/<alloc>?task=web&type=stdout&origin=beginning
// after
GET /v1/client/fs/logs/<alloc>?task=web&type=stdout&origin=start
Defensive patterns

Strategy: validation

Validate before calling

if origin == "" {
    origin = "start"
}
if origin != "start" && origin != "end" {
    return fmt.Errorf("origin must be \"start\" or \"end\", got %q", origin)
}

Type guard

func isValidOrigin(o string) bool {
    return o == "" || o == "start" || o == "end"
}

Try / catch

r, err := client.AllocFS().Logs(alloc, task, "", false, "stdout", origin, 0, ctx.Done(), nil)
if err != nil && strings.Contains(err.Error(), "origin must be start or end") {
    log.Printf("invalid origin %q, using \"start\"", origin)
    return client.AllocFS().Logs(alloc, task, "", false, "stdout", "start", 0, ctx.Done(), nil)
}

Prevention

When it happens

Trigger: Calling stream, logs, Stream, or Logs with req.Origin set to anything other than "start", "end", or empty (empty is defaulted to "start") — e.g. origin=middle or origin=top.

Common situations: Hand-rolled HTTP clients guessing valid values ('beginning', 'tail'); UI passing localized or free-text offset options; casing mistakes like Origin="Start".

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


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/8301d350210bf59c. Report an issue: GitHub.