hashicorp/nomad · warning

Multiple service providers used: task group services must us

Error message

Multiple service providers used: task group services must use the same provider

What it means

MaxClientDisconnect is deprecated in favor of the newer Disconnect block (Disconnect.LostAfter). Setting it on a task group now produces this validation error/warning so specs migrate to the replacement field.

Source

Thrown at nomad/structs/structs.go:7579

				idDuplicateSet.StringFunc(
					func(u unique) string {
						s := u.task + "->" + u.name
						if u.port != "" {
							s += ":" + u.port
						}
						return s
					},
				),
			),
		)
	}

	// The initial feature release of native service discovery only allows for
	// a single service provider to be used across all services in a task
	// group.
	if providerSet.Size() > 1 {
		mErr.Errors = append(mErr.Errors,
			errors.New("Multiple service providers used: task group services must use the same provider"))
	}

	return mErr.ErrorOrNil()
}

// validateScriptChecksInGroupServices ensures group-level services with script
// checks know what task driver to use. Either the service.task or service.check.task
// parameter must be configured.
func (tg *TaskGroup) validateScriptChecksInGroupServices() error {
	var mErr multierror.Error
	for _, service := range tg.Services {
		if service.TaskName == "" {
			for _, check := range service.Checks {
				if check.Type == "script" && check.TaskName == "" {
					mErr.Errors = append(mErr.Errors,
						fmt.Errorf("Service [%s]->%s or Check %s must specify task parameter",
							tg.Name, service.Name, check.Name,
						))

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Remove max_client_disconnect and add a disconnect { lost_after = "..." } block to the group.
  2. Update tooling/templates that emit the deprecated field.
  3. Check the Nomad version's deprecation notes for the exact replacement semantics.

Example fix

// before
group "web" {
  max_client_disconnect = "5m"
}
// after
group "web" {
  disconnect {
    lost_after = "5m"
  }
}
Defensive patterns

Strategy: validation

Validate before calling

if tg.MaxClientDisconnect != nil {
    return errors.New("max_client_disconnect is deprecated; use disconnect { lost_after = ... }")
}

Prevention

When it happens

Trigger: Submitting a job whose group still specifies max_client_disconnect after upgrading to a Nomad version that introduced Disconnect.LostAfter.

Common situations: Old job specs carried forward across a Nomad upgrade; templates or tooling still emitting the deprecated field; docs/examples written pre-1.7.

Related errors


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