Skip to content

Fix persisted cluster reply serialization hangs - #6972

Merged
tim-smart merged 2 commits into
mainfrom
agent/codex-engineer/b564cf01
Aug 4, 2026
Merged

Fix persisted cluster reply serialization hangs#6972
tim-smart merged 2 commits into
mainfrom
agent/codex-engineer/b564cf01

Conversation

@tim-smart

Copy link
Copy Markdown
Contributor

Summary

  • persist a serializable defect reply when a cluster reply cannot be encoded
  • add an in-memory regression test through the real Entity.client → sharding → message-storage path
  • verify the persisted request is completed and the caller receives MalformedMessage instead of hanging

Root cause

Reply.serialize correctly rejects an Error stored inside Schema.Unknown because persisted replies use strict JSON encoding. The resulting MalformedMessage was retried and converted to a defect in the entity response fiber, but no terminal reply was stored, leaving the caller waiting indefinitely.

The reported Effect.orDie omission is not present on current main: the Exit response pipeline already ends with Effect.orDie, and the sibling Chunk, keep-alive, and malformed-input response sites are also guarded. The fix therefore follows the existing RunnerServer behavior for unserializable replies by persisting a serializable defect fallback at the encoded storage boundary.

Validation

  • pnpm test --run packages/effect/test/cluster/Sharding.test.ts
  • pnpm test --run packages/effect/test/cluster/MessageStorage.test.ts
  • pnpm test --run packages/effect/test/cluster/Runners.test.ts
  • pnpm lint-fix
  • pnpm check

Closes EFF-379
Closes #6932

@changeset-bot

changeset-bot Bot commented Aug 4, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 6a23c8d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 30 packages
Name Type
effect Patch
@effect/ai-anthropic Patch
@effect/ai-openai Patch
@effect/ai-openai-compat Patch
@effect/ai-openrouter Patch
@effect/atom-react Patch
@effect/atom-solid Patch
@effect/atom-vue Patch
@effect/docgen Patch
@effect/doctest Patch
@effect/openapi-generator Patch
@effect/opentelemetry Patch
@effect/platform-browser Patch
@effect/platform-bun Patch
@effect/platform-deno Patch
@effect/platform-node Patch
@effect/platform-node-shared Patch
@effect/sql-clickhouse Patch
@effect/sql-d1 Patch
@effect/sql-libsql Patch
@effect/sql-mssql Patch
@effect/sql-mysql2 Patch
@effect/sql-pg Patch
@effect/sql-pglite Patch
@effect/sql-sqlite-bun Patch
@effect/sql-sqlite-do Patch
@effect/sql-sqlite-node Patch
@effect/sql-sqlite-react-native Patch
@effect/sql-sqlite-wasm Patch
@effect/vitest Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@effect-slopcop effect-slopcop Bot added 4.0 bug Something isn't working labels Aug 4, 2026

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

  • .changeset/fix-persisted-cluster-reply-hang.md — patch-level changeset for effect.
  • packages/effect/src/unstable/cluster/MessageStorage.ts — in makeEncoded, wrapped Reply.serialize with a MalformedMessage catch that persists a serializable defect fallback, mirroring the existing RunnerServer fallback.
  • packages/effect/test/cluster/TestEntity.ts — added BoomError with a Schema.Unknown cause and a Fail RPC to trigger the encoding failure.
  • packages/effect/test/cluster/Sharding.test.ts — added a live regression test verifying that the request completes with a die and storage is left with one reply and zero unprocessed messages.

Validation

  • pnpm test --run packages/effect/test/cluster — 55 tests passed.
  • pnpm lint-fix — clean.
  • pnpm check — clean.

Pullfrog  | ⚠️ this action is pinned to a commit SHA, which freezes the cleanup step — switch to @v0 or keep the SHA fresh with Dependabot | View workflow run | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Bundle Size Analysis

Generated from PR build output; treat the content below as untrusted.

File Name Current Size Previous Size Difference
basic.ts 7.06 KB 7.06 KB 0.00 KB (0.00%)
batching.ts 9.86 KB 9.86 KB 0.00 KB (0.00%)
brand.ts 6.34 KB 6.34 KB 0.00 KB (0.00%)
cache.ts 10.62 KB 10.62 KB 0.00 KB (0.00%)
config.ts 20.60 KB 20.60 KB 0.00 KB (0.00%)
differ.ts 20.20 KB 20.20 KB 0.00 KB (0.00%)
http-client.ts 21.49 KB 21.49 KB 0.00 KB (0.00%)
logger.ts 10.76 KB 10.76 KB 0.00 KB (0.00%)
metric.ts 8.98 KB 8.98 KB 0.00 KB (0.00%)
optic.ts 7.18 KB 7.18 KB 0.00 KB (0.00%)
pubsub.ts 14.90 KB 14.90 KB 0.00 KB (0.00%)
queue.ts 11.58 KB 11.58 KB 0.00 KB (0.00%)
schedule.ts 10.74 KB 10.74 KB 0.00 KB (0.00%)
schema-class.ts 19.14 KB 19.14 KB 0.00 KB (0.00%)
schema-fromJsonSchemaDocument.ts 28.96 KB 28.96 KB 0.00 KB (0.00%)
schema-representation-roundtrip.ts 25.29 KB 25.29 KB 0.00 KB (0.00%)
schema-string-transformation.ts 13.30 KB 13.30 KB 0.00 KB (0.00%)
schema-string.ts 10.94 KB 10.94 KB 0.00 KB (0.00%)
schema-template-literal.ts 15.17 KB 15.17 KB 0.00 KB (0.00%)
schema-toArbitraryLazy.ts 21.94 KB 21.94 KB 0.00 KB (0.00%)
schema-toCodeDocument.ts 24.34 KB 24.34 KB 0.00 KB (0.00%)
schema-toCodecJson.ts 19.18 KB 19.18 KB 0.00 KB (0.00%)
schema-toEquivalence.ts 19.01 KB 19.01 KB 0.00 KB (0.00%)
schema-toFormatter.ts 18.87 KB 18.87 KB 0.00 KB (0.00%)
schema-toJsonSchemaDocument.ts 22.60 KB 22.60 KB 0.00 KB (0.00%)
schema-toRepresentation.ts 19.52 KB 19.52 KB 0.00 KB (0.00%)
schema.ts 18.41 KB 18.41 KB 0.00 KB (0.00%)
stm.ts 12.54 KB 12.54 KB 0.00 KB (0.00%)
stream.ts 9.80 KB 9.80 KB 0.00 KB (0.00%)

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

  • packages/effect/src/unstable/cluster/Reply.ts — extracted a shared serializeOrDefect helper that catches MalformedMessage and falls back to a serializable defect reply via Effect.orDie.
  • packages/effect/src/unstable/cluster/MessageStorage.ts — replaced the inline Reply.serialize + encoded.saveReply path with Reply.serializeOrDefect, ensuring persisted unserializable replies terminate instead of hanging.
  • packages/effect/src/unstable/cluster/RunnerServer.ts — replaced the private serializeReply / serializeDefectReply helpers with the shared Reply.serializeOrDefect, keeping non-persisted and persisted reply handling consistent.
  • packages/effect/test/cluster/Sharding.test.ts — regression test verifies the caller gets a die wrapped around MalformedMessage and storage is left with one reply and zero unprocessed messages.

Validation

  • pnpm test --run packages/effect/test/cluster/Sharding.test.ts — 25 tests passed.
  • pnpm test --run packages/effect/test/cluster/MessageStorage.test.ts packages/effect/test/cluster/Runners.test.ts — 10 tests passed.
  • pnpm lint-fix — clean.

Pullfrog  | ⚠️ this action is pinned to a commit SHA, which freezes the cleanup step — switch to @v0 or keep the SHA fresh with Dependabot | View workflow run | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏

@tim-smart
tim-smart merged commit 2235a29 into main Aug 4, 2026
32 of 33 checks passed
@tim-smart
tim-smart deleted the agent/codex-engineer/b564cf01 branch August 4, 2026 21:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

4.0 bug Something isn't working

Projects

None yet

1 participant