ruvnet/ruflo · error · InMemoryFenceReferenceError

expired-fence

expired-fence

Error message

lease ${presented.leaseId} expired

What it means

Thrown when an operation presents a lease whose expiry has passed. Defense: track lease expiry client-side, renew the lease before it expires, and treat expiry as a signal to re-acquire rather than retry the fenced operation.

Source

Thrown at v3/@claude-flow/codex/src/harness/in-memory-fenced-lease-reference.ts:143

      epoch: epoch.toString(),
      version: '1',
      issuedAt: new Date(now).toISOString(),
      expiresAt: new Date(expiresAtMs).toISOString(),
      advisory: true,
    };
    this.leases.set(lease.leaseId, { lease, expiresAtMs });
    return copyLease(lease);
  }

  renew(presented: FencedLease, ttlMs: number): FencedLease {
    if (!Number.isSafeInteger(ttlMs) || ttlMs <= 0) {
      throw new InMemoryFenceReferenceError('invalid-request', 'renewal requires a positive safe ttlMs');
    }
    const stored = this.assertStoredFence(presented);
    const now = this.now();
    if (stored.expiresAtMs <= now) {
      this.leases.delete(presented.leaseId);
      throw new InMemoryFenceReferenceError('expired-fence', `lease ${presented.leaseId} expired`);
    }
    const expiresAtMs = now + ttlMs;
    if (!Number.isSafeInteger(expiresAtMs)) {
      throw new InMemoryFenceReferenceError('invalid-request', 'lease expiry exceeds safe timestamp range');
    }
    const lease: FencedLease = {
      ...stored.lease,
      version: (parseCanonicalUnsigned(stored.lease.version, 'lease version') + 1n).toString(),
      expiresAt: new Date(expiresAtMs).toISOString(),
      scopes: [...stored.lease.scopes],
    };
    this.leases.set(lease.leaseId, { lease, expiresAtMs });
    return copyLease(lease);
  }

  release(presented: FencedLease): void {
    this.assertCurrentFence(presented);
    this.leases.delete(presented.leaseId);

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Re-acquire the lease before presenting it; an expired leaseId cannot be renewed in place.
  2. Shorten the operation or request a longer TTL at acquire time so the lease stays valid for the whole critical section.
  3. Send heartbeats during long operations so the lease does not lapse while work is in progress.
Defensive patterns

Strategy: try-catch

When it happens

Trigger: Thrown at v3/@claude-flow/codex/src/harness/in-memory-fenced-lease-reference.ts:143 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/967854e2370fd204. Report an issue: GitHub.