temporalio/temporal · warning

%w. provided table version: %v current table version: %v

Error message

%w. provided table version: %v current table version: %v

What it means

CreateOrUpdateNexusEndpoint performs an optimistic-concurrency update on the nexus endpoints table: the request carries LastKnownTableVersion, which must equal the current table version row read from Cassandra. When they differ, someone else modified the endpoint table between the caller's read and write, and the persistence layer rejects the write with ErrNexusTableVersionConflict wrapped with both versions.

Source

Thrown at common/persistence/cassandra/nexus_endpoint_store.go:141

		rowType, err := getTypedFieldFromRow[int]("type", row1)
		if err != nil {
			return fmt.Errorf("CreateOrUpdateNexusEndpoint: error reading type from CAS result row: %w", err)
		}
		switch rowType {
		case rowTypePartitionStatus:
			previousPartitionStatus, previousEndpoint = row1, row2
		case rowTypeNexusEndpoint:
			previousPartitionStatus, previousEndpoint = row2, row1
		default:
			return fmt.Errorf("CreateOrUpdateNexusEndpoint: unexpected row type %d in CAS result", rowType)
		}

		currentTableVersion, err := getTypedFieldFromRow[int64]("version", previousPartitionStatus)
		if err != nil {
			return fmt.Errorf("error retrieving current table version: %w", err)
		}
		if currentTableVersion != request.LastKnownTableVersion {
			return fmt.Errorf("%w. provided table version: %v current table version: %v",
				p.ErrNexusTableVersionConflict,
				request.LastKnownTableVersion,
				currentTableVersion)
		}

		currentVersion, err := getTypedFieldFromRow[int64]("version", previousEndpoint)
		if err != nil {
			return fmt.Errorf("error retrieving current endpoint version: %w", err)
		}
		if currentVersion != request.Endpoint.Version {
			return fmt.Errorf("%w. provided endpoint version: %v current endpoint version: %v",
				p.ErrNexusEndpointVersionConflict,
				request.Endpoint.Version,
				currentVersion)
		}

		// This should never happen. This means the request had the correct versions and gocql did not
		// return an error but for some reason the update was not applied.

View on GitHub (pinned to bde624efd1)

Solutions

  1. Re-read the current endpoint/table state and retry the update with the fresh LastKnownTableVersion.
  2. Treat this as an expected conflict: wrap the call in a retry-with-backoff loop that refetches the version on ErrNexusTableVersionConflict.
  3. Serialize admin endpoint mutations through a single path (e.g. frontend leader) to reduce contention.
  4. Check for client code caching table versions across multiple update calls and refresh it each time.

Example fix

// before
_, err := store.CreateOrUpdateNexusEndpoint(ctx, reqWithStaleVersion)
return err // fails on concurrent modification
// after
for attempt := 0; attempt < maxAttempts; attempt++ {
    latest, err := store.GetNexusEndpoints(ctx, pageToken)
    if err != nil {
        return err
    }
    req.LastKnownTableVersion = latest.TableVersion
    _, err = store.CreateOrUpdateNexusEndpoint(ctx, req)
    if !errors.Is(err, p.ErrNexusTableVersionConflict) {
        return err
    }
}
Defensive patterns

Strategy: retry

Validate before calling

current, err := store.GetNexusEndpoints(ctx, token) // refetch before write
if err != nil {
    return err
}
if current.TableVersion != req.LastKnownTableVersion {
    req.LastKnownTableVersion = current.TableVersion // refresh instead of failing
}

Type guard

func isTableVersionConflict(err error) bool {
    return errors.Is(err, p.ErrNexusTableVersionConflict)
}

Try / catch

_, err := store.CreateOrUpdateNexusEndpoint(ctx, req)
if errors.Is(err, p.ErrNexusTableVersionConflict) {
    // concurrent modification: refetch table version and retry with backoff
    return retryWithFreshVersion(ctx, req)
}
return err

Prevention

When it happens

Trigger: Two concurrent admin/frontend calls to CreateOrUpdateNexusEndpoint (or an update racing a create/delete) using a stale LastKnownTableVersion; also exercised by concurrent-update tests like testCassandraNexusEndpointStoreConcurrentUpdate.

Common situations: Multiple operators updating Nexus endpoints (callbacks, workers) simultaneously via tctl/UI; a frontend instance holding a cached table version while another instance already bumped it; retries of an old request after a competing write succeeded.

Related errors


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