diegosouzapw/OmniRoute · error

[bottleneck-patch] _startHeartbeat not found on…

Error message

[bottleneck-patch] _startHeartbeat not found on LocalDatastore, patch skipped

What it means

Non-fatal patch notice: applyBottleneckHeartbeatPatch probes Bottleneck's LocalDatastore prototype (via a throwaway instance, since the class is not exported) to fix its heartbeat/clearInterval semantics, but the expected `_startHeartbeat` method is absent — the installed bottleneck version differs from what the patch targets. The heartbeat patch is skipped and stock Bottleneck behavior remains; nothing crashes.

Solutions

  1. Check the installed bottleneck version against the version the patch was written for; pin or bump accordingly.
  2. Update the patch to match the new LocalDatastore internals (method names may have changed).
  3. If stock behavior is acceptable, silence the warning explicitly to reduce noise.
Defensive patterns

Strategy: fallback

When it happens

Trigger: Thrown at open-sse/services/bottleneckPatch.ts:67 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of diegosouzapw/OmniRoute@a179ffed5b (2026-08-25). Data as JSON: /api/errors/746f5dc21043a638. Report an issue: GitHub.

Appendix: source

Thrown at open-sse/services/bottleneckPatch.ts:67

 * Fixed semantics:
 *  - refresh config present, no live interval → create (delegate to the original).
 *  - refresh config present, interval alive   → keep it (interval reads storeOptions
 *    live, so updated amounts are picked up) — upstream wrongly killed it here.
 *  - refresh config absent, interval alive    → clearInterval AND null the handle.
 */
export function applyBottleneckHeartbeatPatch(): void {
  if (heartbeatPatched) return;
  heartbeatPatched = true;

  // LocalDatastore is not exported; reach its prototype through a throwaway instance.
  const probe = new Bottleneck({});
  const store = (probe as unknown as { _store: BottleneckLocalDatastore })._store;
  const proto = Object.getPrototypeOf(store) as BottleneckLocalDatastore;
  void probe.disconnect();

  const originalStartHeartbeat = proto._startHeartbeat;
  if (typeof originalStartHeartbeat !== "function") {
    console.warn("[bottleneck-patch] _startHeartbeat not found on LocalDatastore, patch skipped");
    return;
  }

  proto._startHeartbeat = function patchedStartHeartbeat(this: BottleneckLocalDatastore) {
    const opts = this.storeOptions ?? {};
    const wantsHeartbeat =
      (opts.reservoirRefreshInterval != null && opts.reservoirRefreshAmount != null) ||
      (opts.reservoirIncreaseInterval != null && opts.reservoirIncreaseAmount != null);

    if (this.heartbeat != null) {
      if (wantsHeartbeat) return; // alive and still wanted — upstream wrongly cleared it here
      clearInterval(this.heartbeat);
      this.heartbeat = null; // upstream forgot this null-out — the core of the bug
      return;
    }
    return originalStartHeartbeat.call(this);
  };

View on GitHub (pinned to a179ffed5b)