hashicorp/nomad · error

expose may only be set for Consul service checks

Error message

expose may only be set for Consul service checks

What it means

In Nomad service checks (validateNomad path), the expose field is a Consul Connect-specific feature; setting it on a check of a service that is not backed by Consul is rejected. Nomad-side checks have no envoy expose configuration.

Source

Thrown at nomad/structs/services.go:359

	// validate check_restart
	if err := sc.CheckRestart.Validate(); err != nil {
		return err
	}

	return nil
}

// validate a Service's ServiceCheck in the context of the Nomad provider.
func (sc *ServiceCheck) validateNomad() error {
	allowable := []string{ServiceCheckTCP, ServiceCheckHTTP}
	if err := sc.validateCommon(allowable); err != nil {
		return err
	}

	// expose is connect (consul) specific
	if sc.Expose {
		return errors.New("expose may only be set for Consul service checks")
	}

	// nomad checks do not have warnings
	if sc.OnUpdate == OnUpdateIgnoreWarn {
		return errors.New("on_update may only be set to ignore_warnings for Consul service checks")
	}

	// below are temporary limitations on checks in nomad
	// https://github.com/hashicorp/team-nomad/issues/354

	// check_restart.ignore_warnings is not a thing in Nomad (which has no warnings in checks)
	if sc.CheckRestart != nil {
		if sc.CheckRestart.IgnoreWarnings {
			return errors.New("ignore_warnings on check_restart only supported for Consul service checks")
		}
	}

	// address_mode="driver" not yet supported on nomad

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Remove expose = true from the check
  2. Switch the service to provider = "consul" with a connect stanza if expose is genuinely needed
  3. Re-run nomad job validate to confirm

Example fix

// before
service {
  provider = "nomad"
  check {
    expose = true
  }
}
// after
service {
  provider = "nomad"
  check {
    # expose removed
  }
}
Defensive patterns

Strategy: validation

Validate before calling

if check.Expose && service.Provider != "consul" {
    return fmt.Errorf("check %q: expose requires provider = \"consul\"", check.Name)
}

Try / catch

if err := job.Validate(); err != nil {
    var ve *jobValidationError
    if errors.As(err, &ve) && strings.Contains(ve.Error(), "expose may only be set") {
        // strip expose or switch provider to consul
    }
}

Prevention

When it happens

Trigger: A job defines a service check with expose = true while the service provider is not Consul (e.g. provider = "nomad" or no connect block).

Common situations: Copying Consul connect service stanzas into nomad-provider services; enabling expose for a plain Nomad check; converting jobs from Consul to Nomad service discovery without removing expose.

Related errors


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