hashicorp/nomad · error

Consul Connect service name %q in group %q must not contain

Error message

Consul Connect service name %q in group %q must not contain uppercase characters

What it means

Consul assumes Connect service names are lowercase and does not validate this itself, so Nomad pre-validates on job submission: a connect sidecar service whose `name` contains uppercase characters is rejected. The check compares the service name against its lowercased form in groupConnectSidecarValidate.

Source

Thrown at nomad/job_endpoint_hook_connect.go:664

	allowed := `"bridge" or "cni/*"`
	if allowHost {
		allowed = `"bridge", "host", or "cni/*"`
	}
	return fmt.Errorf("%s: %w: group %q uses network mode %q; must be %s",
		errorPrefix, ErrConnectInvalidNetworkMode, g.Name, mode, allowed)
}

func groupConnectSidecarValidate(g *structs.TaskGroup, s *structs.Service) error {
	if err := groupConnectNetworkModeValidate(g, "connect sidecar", false); err != nil {
		return err
	}

	// We must enforce lowercase characters on group and service names for connect
	// sidecar proxies, because Consul assumes this invariant without validating it.
	// https://github.com/hashicorp/consul/blob/v1.9.5/command/connect/proxy/proxy.go#L235

	if s.Name != strings.ToLower(s.Name) {
		return fmt.Errorf("Consul Connect service name %q in group %q must not contain uppercase characters", s.Name, g.Name)
	}

	if g.Name != strings.ToLower(g.Name) {
		return fmt.Errorf("Consul Connect group %q with service %q must not contain uppercase characters", g.Name, s.Name)
	}

	return nil
}

func groupConnectNativeValidate(g *structs.TaskGroup, s *structs.Service) error {
	// note that network mode is not enforced for connect native services

	if _, err := getNamedTaskForNativeService(g, s.Name, s.TaskName); err != nil {
		return err
	}
	return nil
}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Lowercase the connect service `name` in the job file (e.g. "myapi").
  2. If display casing matters, keep the connect service name lowercase and use tags/metadata for the original casing.
  3. If the service is not a connect sidecar, remove the connect block so this validation does not apply.

Example fix

// before
service {
  name = "PaymentService"
  connect { sidecar_service {} }
}
// after
service {
  name = "paymentservice"
  connect { sidecar_service {} }
}
Defensive patterns

Strategy: validation

Validate before calling

function validateConnectServiceName(group, service) {
  if (service.connect && service.name !== service.name.toLowerCase()) {
    throw new Error(`connect service name "${service.name}" must be lowercase`);
  }
}

Type guard

function isLowercase(s) { return typeof s === 'string' && s === s.toLowerCase(); }

Prevention

When it happens

Trigger: Submitting a job with a connect sidecar service where `service { name = "MyAPI" }` (or any name with A-Z) triggers `s.Name != strings.ToLower(s.Name)`.

Common situations: PascalCase or camelCase service names copied from application conventions; names auto-generated from uppercase Docker image or repo names; users unaware Consul requires lowercase DNS-compatible names.

Related errors


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