temporalio/temporal · error

invalid operation token

Error message

invalid operation token

What it means

validateCAs iterates a list of CA entries (inline PEM data or file paths) and rejects any entry whose TrimSpace is empty. This is a guard against silently building an empty or malformed CA pool from blank list items, which would cause hard-to-debug TLS verification failures later.

Source

Thrown at chasm/lib/nexusoperation/task_handler_helpers.go:28

	"time"

	"github.com/nexus-rpc/sdk-go/nexus"
	commonpb "go.temporal.io/api/common/v1"
	enumspb "go.temporal.io/api/enums/v1"
	failurepb "go.temporal.io/api/failure/v1"
	"go.temporal.io/api/serviceerror"
	persistencespb "go.temporal.io/server/api/persistence/v1"
	tokenspb "go.temporal.io/server/api/token/v1"
	"go.temporal.io/server/common"
	"go.temporal.io/server/common/namespace"
	commonnexus "go.temporal.io/server/common/nexus"
	"go.temporal.io/server/common/nexus/nexusrpc"
	queueserrors "go.temporal.io/server/service/history/queues/errors"
)

var (
	ErrResponseBodyTooLarge  = errors.New("http: response body too large")
	ErrInvalidOperationToken = errors.New("invalid operation token")
	errRequestTimedOut       = errors.New("request timed out")
	errOpProcessorFailed     = errors.New("nexus operation processor failed")
)

const maxDuration = time.Duration(1<<63 - 1)

type operationTimeoutBelowMinError struct {
	timeoutType enumspb.TimeoutType
}

func (o *operationTimeoutBelowMinError) Error() string {
	return fmt.Sprintf("not enough time to execute another request before %s timeout", o.timeoutType.String())
}

func isDestinationDown(err error) bool {
	if _, ok := errors.AsType[serviceerror.ServiceError](err); ok {
		return false
	}

View on GitHub (pinned to bde624efd1)

Solutions

  1. Delete the empty entry from the CA list in your config.
  2. Fix whatever produced the blank value (unset env var, missing secret, bad template).
  3. If a CA is optional, omit the entry entirely instead of passing "".
  4. Pre-validate the rendered config with a script that trims and drops blank CA entries before startup.

Example fix

// before
RootCAData: ["-----BEGIN CERTIFICATE-----...", "  "]
// after
RootCAData: ["-----BEGIN CERTIFICATE-----..."]
Defensive patterns

Strategy: validation

Validate before calling

func hasEmptyCA(cas []string) bool {
	for _, ca := range cas {
		if strings.TrimSpace(ca) == "" {
			return true
		}
	}
	return false
}

Prevention

When it happens

Trigger: Any validateServerTLS or validateClientTLS path where ClientCAData/ClientCAFiles/RootCAData/RootCAFiles contains "" or a whitespace-only string.

Common situations: Empty YAML list items, env-var substitution expanding to nothing, unfilled template placeholders, secret mount not present so data is blank, copy-paste trailing empty element.

Related errors


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