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
- Re-read the current endpoint/table state and retry the update with the fresh LastKnownTableVersion.
- Treat this as an expected conflict: wrap the call in a retry-with-backoff loop that refetches the version on ErrNexusTableVersionConflict.
- Serialize admin endpoint mutations through a single path (e.g. frontend leader) to reduce contention.
- 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
- Always fetch the current table version immediately before an update; never cache it across calls
- Implement bounded retry-with-backoff on ErrNexusTableVersionConflict in admin tooling
- Route endpoint mutations through a single coordination point to reduce write contention
- Monitor conflict rates; sustained conflicts indicate a stale-version client bug
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
- error while updating cluster metadata: %w
- cassandra schema version compatibility check failed: %w
- unable to decode cassandra serial consistency: %v
- invalid task schema version
- membershipExpiry duration should be atleast 1 second
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/058ae08f61518554.
Report an issue: GitHub.