temporalio/temporal · error

empty operation name

Error message

empty operation name

What it means

errEmptyOperationName is a sentinel in common/nexus/nexusrpc/client.go indicating NewOperationHandle was called with an empty operation name. An operation handle needs a valid operation identifier to form request URLs, so an empty name is rejected up front rather than producing malformed HTTP requests later.

Source

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

	// Service name. Required.
	Service string
	// A function for making HTTP requests.
	// Defaults to [http.DefaultClient.Do].
	HTTPCaller func(*http.Request) (*http.Response, error)
	// A [Serializer] to customize client serialization behavior.
	// By default the client handles JSONables, byte slices, and nil.
	Serializer nexus.Serializer
	// A [FailureConverter] to convert a [Failure] instance to and from an [error]. Defaults to
	// [DefaultFailureConverter].
	FailureConverter FailureConverter
}

// User-Agent header set on HTTP requests.
const userAgent = "temporalio/server"

const headerUserAgent = "User-Agent"

var errEmptyOperationName = errors.New("empty operation name")

var errEmptyOperationToken = errors.New("empty operation token")

// UnexpectedResponseError indicates a client encountered something unexpected in the server's response.
type UnexpectedResponseError struct {
	// Error message.
	Message string
	// Optional failure that may have been emedded in the response.
	Failure *nexus.Failure
	// Additional transport specific details.
	// For HTTP, this would include the HTTP response. The response body will have already been read into memory and
	// does not need to be closed.
	Details any
}

// Error implements the error interface.
func (e *UnexpectedResponseError) Error() string {
	return e.Message

View on GitHub (pinned to bde624efd1)

Solutions

  1. Ensure the operation name is populated before calling NewOperationHandle
  2. Check with errors.Is(err, nexusrpc.ErrEmptyOperationName) to detect this case
  3. If the name is derived from input, fail earlier with a clear user-facing message when it is empty

Example fix

// before
handle, err := client.NewOperationHandle(ctx, "", token)
// after
if operationName == "" {
    return nil, fmt.Errorf("operation name required")
}
handle, err := client.NewOperationHandle(ctx, operationName, token)
Defensive patterns

Strategy: validation

Validate before calling

func checkHandleArgs(operationName, token string) error {
    if operationName == "" { return errors.New("operation name required") }
    return nil
}

Type guard

func hasOperationName(name string) bool { return name != "" }

Try / catch

handle, err := client.NewOperationHandle(ctx, opName, token)
if errors.Is(err, nexusrpc.ErrEmptyOperationName) {
    return fmt.Errorf("cannot create handle: operation name is empty")
}

Prevention

When it happens

Trigger: Calling NewOperationHandle (typically via a nexus client) with operationName == "", e.g. when the name comes from an unset config value, an empty workflow input, or a struct field that was never populated.

Common situations: Programmatic clients that derive operation names from data where the field may be absent; tests verifying failure conditions (TestNewHandleFailureConditions); serialization round-trips that drop an empty optional name field.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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