temporalio/temporal · error

empty Service

Error message

empty Service

What it means

NewHTTPClient requires HTTPClientOptions.Service to be set; this string identifies the target Nexus service and is used in request paths/metrics. An empty Service means the client cannot address requests correctly, so construction fails with this error after the BaseURL check.

Source

Thrown at common/nexus/nexusrpc/client.go:162

//
// [Nexus HTTP API]: https://github.com/nexus-rpc/api
type HTTPClient struct {
	baseHTTPClient
	service        string
	serviceBaseURL *url.URL
}

// NewHTTPClient creates a new [HTTPClient] from provided [HTTPClientOptions].
// BaseURL and Service are required.
func NewHTTPClient(options HTTPClientOptions) (*HTTPClient, error) {
	if options.HTTPCaller == nil {
		options.HTTPCaller = http.DefaultClient.Do
	}
	if options.BaseURL == "" {
		return nil, errors.New("empty BaseURL")
	}
	if options.Service == "" {
		return nil, errors.New("empty Service")
	}
	var baseURL *url.URL
	var err error
	baseURL, err = url.Parse(options.BaseURL)
	if err != nil {
		return nil, err
	}
	if baseURL.Scheme != "http" && baseURL.Scheme != "https" {
		return nil, fmt.Errorf("invalid URL scheme: %s", baseURL.Scheme)
	}
	if options.Serializer == nil {
		options.Serializer = nexus.DefaultSerializer()
	}
	if options.FailureConverter == nil {
		options.FailureConverter = DefaultFailureConverter()
	}
	return &HTTPClient{
		baseHTTPClient: baseHTTPClient{

View on GitHub (pinned to bde624efd1)

Solutions

  1. Set Service in HTTPClientOptions to the name of the target Nexus service
  2. Fix the config source so the service name is populated
  3. Validate required options (BaseURL and Service) before constructing the client

Example fix

// before
opts := nexusrpc.HTTPClientOptions{BaseURL: endpoint}
// after
opts := nexusrpc.HTTPClientOptions{BaseURL: endpoint, Service: "nexus-test-service"}
Defensive patterns

Strategy: validation

Validate before calling

func validateHTTPOptions(opts nexusrpc.HTTPClientOptions) error {
    if opts.Service == "" { return errors.New("Service required") }
    return nil
}

Type guard

func hasService(opts nexusrpc.HTTPClientOptions) bool { return opts.Service != "" }

Try / catch

client, err := nexusrpc.NewHTTPClient(opts)
if err != nil && strings.Contains(err.Error(), "empty Service") {
    return nil, fmt.Errorf("nexus service name not configured: %w", err)
}

Prevention

When it happens

Trigger: Calling NewHTTPClient with HTTPClientOptions where Service is "" while BaseURL is set — e.g. config that supplies an endpoint but not the service name.

Common situations: Partial configuration where only the URL was provided; renaming a Nexus service and forgetting to update the client options; tests and helpers (setupCustom, nexusClientForActiveCluster) wiring options from sparse config.

Understand the failure class

Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.

Related errors


AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01). Data as JSON: /api/errors/f551c18834b9654e. Report an issue: GitHub.