hashicorp/nomad · error

tls_server_name may only be set for Consul service checks

Error message

tls_server_name may only be set for Consul service checks

What it means

ServiceCheck.Validate in nomad/structs/services.go rejects TLSServerName on checks that are not Consul provider checks. The tls_server_name field configures SNI/hostname verification and is only forwarded to Consul; Nomad-native checks have no use for it. validateNomad is the provider-specific validation path, so setting the field there is a configuration error.

Source

Thrown at nomad/structs/services.go:405

	// success_before_passing is consul only
	if sc.SuccessBeforePassing != 0 {
		return errors.New("success_before_passing may only be set for Consul service checks")
	}

	// failures_before_critical is consul only
	if sc.FailuresBeforeCritical != 0 {
		return errors.New("failures_before_critical may only be set for Consul service checks")
	}

	// failures_before_warning is consul only
	if sc.FailuresBeforeWarning != 0 {
		return errors.New("failures_before_warning may only be set for Consul service checks")
	}

	// tls_server_name is consul only
	if sc.TLSServerName != "" {
		return errors.New("tls_server_name may only be set for Consul service checks")
	}

	return nil
}

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

	checkType := strings.ToLower(sc.Type)

	// Note that we cannot completely validate the Expose field yet - we do not
	// know whether this ServiceCheck belongs to a connect-enabled group-service.
	// Instead, such validation will happen in a job admission controller.
	//

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Remove the tls_server_name field from checks on services that use the nomad provider
  2. Switch the service's provider to "consul" if SNI hostname override is genuinely needed
  3. Use check TLS-related options supported by nomad checks (e.g. tls_skip_verify) instead

Example fix

// before
check {
  type            = "http"
  tls_server_name = "my-service.service.consul"
}
// after
check {
  type            = "http"
  provider        = "consul"
  tls_server_name = "my-service.service.consul"
}
Defensive patterns

Strategy: validation

Validate before calling

function checkTLSServerName(service) {
  if ((service.provider ?? "consul") !== "consul") {
    for (const c of service.checks ?? []) {
      if (c.tls_server_name) throw new Error(`check on ${service.name}: tls_server_name is consul-only`);
    }
  }
}

Type guard

function isConsulCheck(c) { return typeof c.tls_server_name === "undefined" || c.tls_server_name === ""; }

Try / catch

try {
  await nomad.jobs.validate(job);
} catch (e) {
  if (e.message.includes("tls_server_name may only be set for Consul")) {
    console.error("Remove tls_server_name from nomad-provider checks");
  } else throw e;
}

Prevention

When it happens

Trigger: Defining a task/group service check with provider = "nomad" (or default provider nomad) while setting check.tls_server_name to a non-empty value, then submitting/validating the job.

Common situations: Copying a check block that worked under Consul to a Nomad-provider service; teams migrating off Consul who keep the TLS tuning fields; templates that blanket-apply tls_server_name to all checks.

Related errors


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