Skip to content

Comments

fix(shared-log): avoid unhandled rejection when entry.hash is missing#591

Open
Faolain wants to merge 1 commit intodao-xyz:masterfrom
Faolain:fix/shared-log-unhandled-persistcoordinate
Open

fix(shared-log): avoid unhandled rejection when entry.hash is missing#591
Faolain wants to merge 1 commit intodao-xyz:masterfrom
Faolain:fix/shared-log-unhandled-persistcoordinate

Conversation

@Faolain
Copy link
Contributor

@Faolain Faolain commented Feb 5, 2026

tl;dr Mainly saw this while testing, spinning up and tearing down quickly (in parallel), I know you have tests set up sequentially but I was curious what was actually happening and why this was the case. I figured churning nodes could also be a good usecase for real network topology, especially with the fanout tree + large network sims plan.
test failure seems unrelated and is a flake that has been see before?

Problem

In @peerbit/shared-log, _waitForReplicators() invokes an async check() from event listeners without awaiting/catching it. If check() rejects (e.g. because findLeaders() calls persistCoordinate() with an entry that is missing/invalid entry.hash), Node emits an unhandledRejection.

This shows up as a flaky failure in highly-concurrent test runners (Vitest) and can also surface in production as noisy unhandledrejection events (browser) or process failure depending on Node --unhandled-rejections mode.

Observed stack trace

Captured by a minimal script that calls _waitForReplicators() with an entry-like object whose hash is undefined:

TypeError: Cannot read properties of undefined (reading 'multihash')
    at SharedLog.persistCoordinate (.../packages/programs/data/shared-log/dist/src/index.js:2597:85)
    at SharedLog.findLeaders (.../packages/programs/data/shared-log/dist/src/index.js:2678:37)
    at async check (.../packages/programs/data/shared-log/dist/src/index.js:2548:37)

Fix

  1. Make persistCoordinate() defensive: if entry.hash is missing/empty/invalid (or if cidifyString(hash) fails/returns undefined), return early.
  2. Wrap _waitForReplicators()'s internal check() calls in a safeCheck() that catches rejections so they don't become unhandled promise rejections when triggered from event listeners.

Test

Adds packages/programs/data/shared-log/test/unhandled-rejection.spec.ts to assert that _waitForReplicators() does not emit unhandledRejection when the internal check() path fails.

Run:

  • pnpm --filter @peerbit/shared-log test

- Guard persistCoordinate when entry.hash is missing/invalid
- Wrap _waitForReplicators() check() calls to avoid unhandled rejections
- Add regression test covering the failure mode
@Faolain
Copy link
Contributor Author

Faolain commented Feb 5, 2026

I couldn't reproduce the @peerbit/document test failure locally on the PR head (7789ac9).

I ran:

pnpm run build
pnpm run test:ci:part-2

And also re-ran the specific test 10x:

pnpm --filter @peerbit/document test -- --grep "can search while keeping minimum amount of replicas"

All passing locally. This looks like a flake (?) ; a rerun of the CI job would help confirm.

@Faolain
Copy link
Contributor Author

Faolain commented Feb 6, 2026

AI Reviews

Screenshot 2026-02-06 at 12 06 09 AM

Background on how Error was found

Screenshot 2026-02-06 at 12 10 44 AM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant