hashicorp/nomad · error

first message should always be setup

Error message

first message should always be setup

What it means

The ExecStreaming gRPC handler requires the very first message on the stream to contain the Setup field (command and tty configuration). This error is returned when the client opens the stream but sends a message whose Setup is nil, or a non-setup message first.

Source

Thrown at drivers/shared/executor/grpc_server.go:178

	out, exit, err := s.impl.Exec(deadline, req.Cmd, req.Args)
	if err != nil {
		return nil, err
	}

	return &proto.ExecResponse{
		Output:   out,
		ExitCode: int32(exit),
	}, nil
}

func (s *grpcExecutorServer) ExecStreaming(server proto.Executor_ExecStreamingServer) error {
	msg, err := server.Recv()
	if err != nil {
		return fmt.Errorf("failed to receive initial message: %v", err)
	}

	if msg.Setup == nil {
		return fmt.Errorf("first message should always be setup")
	}

	return s.impl.ExecStreaming(server.Context(),
		msg.Setup.Command, msg.Setup.Tty,
		server)
}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Always send ExecTaskStreamingRequest{Setup: &proto.ExecTaskStreamingRequest_Setup{...}} as the first stream message
  2. Ensure client and server use the same nomad protobuf definitions (match Nomad versions)
  3. Validate the setup payload is populated before calling stream.Send
  4. Regenerate proto bindings if a custom client's generated code is stale

Example fix

// before
stream.Send(&proto.ExecTaskStreamingRequest{}) // no Setup
// after
stream.Send(&proto.ExecTaskStreamingRequest{Setup: &proto.ExecTaskStreamingRequest_Setup{Command: cmd, Tty: false}})
Defensive patterns

Strategy: validation

Validate before calling

if req.Setup == nil { return errors.New("setup must be sent first") } // client-side pre-send check

Try / catch

if err := stream.Send(setupFirst); err != nil {
    if strings.Contains(err.Error(), "first message should always be setup") { fix client ordering }
}

Prevention

When it happens

Trigger: Client sends an empty ExecTaskStreamingRequest, sends an input/resize message before setup, or a client/server proto version mismatch causes Setup to be dropped.

Common situations: Hand-rolled or version-mismatched clients speaking to the executor gRPC API; upgrading Nomad agents/executors out of sync so proto fields deserialize differently; buggy custom tooling around alloc exec.

Related errors


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