temporalio/temporal · error

empty BaseURL

Error message

empty BaseURL

What it means

NewHTTPClient in common/nexus/nexusrpc/client.go requires HTTPClientOptions.BaseURL to be set; when it is empty the client cannot parse a target URL and returns this error immediately. BaseURL is the endpoint of the remote Nexus endpoint/service all requests will be sent to.

Source

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

//
// OperationHandles can be obtained either by starting new operations or by calling [HTTPClient.NewOperationHandle] for
// existing operations.
//
// [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()

View on GitHub (pinned to bde624efd1)

Solutions

  1. Set HTTPClientOptions.BaseURL to the full Nexus endpoint URL (e.g. http://host:port) before calling NewHTTPClient
  2. Fix the config/env source so the endpoint value is actually loaded
  3. Validate options.BaseURL is non-empty at startup to fail fast with a clearer message

Example fix

// before
client, err := nexusrpc.NewHTTPClient(nexusrpc.HTTPClientOptions{Service: "test"})
// after
client, err := nexusrpc.NewHTTPClient(nexusrpc.HTTPClientOptions{
    Service: "test",
    BaseURL: cfg.NexusEndpointURL, // e.g. "http://127.0.0.1:7243"
})
Defensive patterns

Strategy: validation

Validate before calling

func validateHTTPOptions(opts nexusrpc.HTTPClientOptions) error {
    if opts.BaseURL == "" { return errors.New("BaseURL required") }
    if _, err := url.Parse(opts.BaseURL); err != nil { return err }
    return nil
}

Type guard

func hasBaseURL(opts nexusrpc.HTTPClientOptions) bool { return opts.BaseURL != "" }

Try / catch

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

Prevention

When it happens

Trigger: Calling NewHTTPClient with HTTPClientOptions where BaseURL is "" — typically from setupCustom, nexusClientForActiveCluster, or config-driven construction where the endpoint setting was missing.

Common situations: Missing or misnamed config key for the Nexus endpoint; environment variable not set so the endpoint string stays empty; running against a cluster that has not been configured with Nexus endpoints.

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/1e5cfc220c0fcf0a. Report an issue: GitHub.