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
- Set Service in HTTPClientOptions to the name of the target Nexus service
- Fix the config source so the service name is populated
- 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
- Keep BaseURL and Service in the same config block so they are set together
- Reference service names via constants instead of ad-hoc strings
- Validate the full HTTPClientOptions struct in one place before constructing clients
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
- empty BaseURL
- invalid config type: %T for nexusoperation.callback.endpoint
- unknown archiver scheme
- unable to find archiver config for the given scheme
- no bucket specified
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/f551c18834b9654e.
Report an issue: GitHub.