apache/beam · warning

RCSP : Subsequent run that doesn't hold the lock . This is…

Error message

RCSP  {} : Subsequent run that doesn't hold the lock {}. This is not unexpected and should probably be reviewed.

What it means

ReadChangeStreamPartitionAction.run logs 'RCSP <partition>: Subsequent run that doesn't hold the lock <uuid>' when a retried attempt of the same partition/uuid does not pass the lock verification, meaning this worker is processing a partition whose lock it does not (or no longer) hold. The connector marks streamProgress.setFailToLock(true) so the partition is re-assigned.

Solutions

  1. Usually safe to ignore: the connector fails the lock and the partition will be retried/assigned correctly.
  2. If it repeats persistently, check for multiple pipeline instances streaming the same change stream concurrently.
  3. Verify the app profile allows multi-row transactions and that the metadata table is healthy.
  4. Report/upgrade if the lock check consistently fails despite a single runner (known review-needed warning per the message).

Example fix

// before
// two streaming jobs reading the same change stream -> lock contention
// after
// stop the duplicate job; keep exactly one ReadChangeStream pipeline per stream
Defensive patterns

Strategy: retry

Try / catch

try { partitionAction.run(record, receiver); } catch (RuntimeException e) { /* runner retries; connector sets failToLock and reassigns the partition */ }

Prevention

When it happens

Trigger: A bundle retry of ReadChangeStreamPartitionAction for the same PartitionRecord uuid after the lock was released/cleaned up (e.g. a retry of CloseStream), or the restriction tracker/lock state changed between attempts.

Common situations: Runner-level bundle retries after transient failures; work stealing/reassignment where another worker already processed the partition; race during CloseStream cleanup.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/f985288440ee5e91. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigtable/changestreams/action/ReadChangeStreamPartitionAction.java:172

            "RCSP  {} : Could not acquire lock with uid: {}, because this is a "
                + "duplicate and another worker is working  on this partition already.",
            formatByteStringRange(partitionRecord.getPartition()),
            partitionRecord.getUuid());
        StreamProgress streamProgress = new StreamProgress();
        streamProgress.setFailToLock(true);
        metrics.decPartitionStreamCount();
        tracker.tryClaim(streamProgress);
        return ProcessContinuation.stop();
      }
    } else if (tracker.currentRestriction().getCloseStream() == null
        && !metadataTableDao.doHoldLock(
            partitionRecord.getPartition(), partitionRecord.getUuid())) {
      // We only verify the lock if we are not holding CloseStream because if this is a retry of
      // CloseStream we might have already cleaned up the lock in a previous attempt.
      // Failed correctness check on this worker holds the lock on this partition. This shouldn't
      // fail because there's a restriction tracker which means this worker has already acquired the
      // lock and once it has acquired the lock it shouldn't fail the lock check.
      LOG.warn(
          "RCSP  {} : Subsequent run that doesn't hold the lock {}. This is not unexpected and "
              + "should probably be reviewed.",
          formatByteStringRange(partitionRecord.getPartition()),
          partitionRecord.getUuid());
      StreamProgress streamProgress = new StreamProgress();
      streamProgress.setFailToLock(true);
      metrics.decPartitionStreamCount();
      tracker.tryClaim(streamProgress);
      return ProcessContinuation.stop();
    }

    // Process CloseStream if it exists
    CloseStream closeStream = tracker.currentRestriction().getCloseStream();
    if (closeStream != null) {
      LOG.debug("RCSP: Processing CloseStream");
      metrics.decPartitionStreamCount();
      if (closeStream.getStatus().getCode() == Status.Code.OK) {
        // We need to update watermark here. We're terminating this stream because we have reached

View on GitHub (pinned to 12126d8942)