Skip to content

Add reproduction for MutableList issue - #6847

Merged
tim-smart merged 2 commits into
mainfrom
audit/repro-core-mutablelist-prepend-tail
Aug 2, 2026
Merged

Add reproduction for MutableList issue#6847
tim-smart merged 2 commits into
mainfrom
audit/repro-core-mutablelist-prepend-tail

Conversation

@fubhy

@fubhy fubhy commented Aug 1, 2026

Copy link
Copy Markdown
Member

Reproduction only

This PR adds reproduction tests only. No implementation fix is included. CI is expected to fail until the underlying issue is fixed.

Covered audit issues

1. core-g-r-mutablelist-empty-prepend-tail-invariant: Prepending to an empty list leaves the tail unset

Module: MutableList

Expected contract: Prepending to an empty list creates a sole node that is both head and tail; later append preserves that node and list traversal agrees with length.

Observed result: The intended assertion failed; an independent probe produced values [2, null] with length 2.

Reproduction command:

pnpm vitest run packages/effect/test/MutableList.test.ts -t "preserves a prepended element when appending to the list"

2. core-g-r-mutablelist-negative-toarrayn-bound: toArrayN throws for a negative bound

Module: MutableList

Expected contract: toArrayN returns up to n values as a bounded prefix; for a nonpositive bound it returns an empty snapshot, consistent with sibling takeN.

Observed result: The intended failure was reproduced with RangeError: Invalid array length.

Reproduction command:

pnpm vitest run packages/effect/test/MutableList.test.ts -t "returns an empty snapshot for a negative bound"

@github-project-automation github-project-automation Bot moved this to Discussion Ongoing in PR Backlog Aug 1, 2026
@changeset-bot

changeset-bot Bot commented Aug 1, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: d959a71

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/opentelemetry Patch
@effect/platform-browser Patch
@effect/platform-bun Patch
@effect/platform-deno Patch
@effect/platform-node-shared Patch
@effect/platform-node Patch
@effect/vitest Patch
@effect/ai-anthropic Patch
@effect/ai-openai-compat Patch
@effect/ai-openai Patch
@effect/ai-openrouter Patch
@effect/atom-react Patch
@effect/atom-solid Patch
@effect/atom-vue 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/docgen Patch
@effect/doctest Patch
@effect/openapi-generator 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 the 4.0 label Aug 1, 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 — added two reproduction-only tests for MutableList bugs:

  • prepend on empty list doesn't set tail — subsequent append overwrites the head bucket, losing the prepended element
  • toArrayN missing negative-bound guardMath.min(-1, length) passes through to new Array(-1), throwing RangeError (contrast with takeN, which already has if (n <= 0) return [])

Both tests are well-structured, use the correct assertion utilities, follow existing test patterns, and were verified to fail against current code.

Pullfrog  | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) (Kimi K2 not used — the program covers this model; add its provider key to run your pick) | 𝕏

@effect-slopcop effect-slopcop Bot added the bug Something isn't working label Aug 1, 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 critical issues — one scope observation below.

Reviewed changes — added fixes for the two MutableList bugs reproduced in the prior commit:

  • prepend now initializes tail on empty list — a new guard if (!self.tail) self.tail = self.head ensures the prepended node serves as both head and tail, so subsequent append calls extend rather than overwrite.
  • toArrayN guards non-positive bounds — the new if (n <= 0) return [] guard matches the existing pattern in takeN and takeNVoid, preventing new Array(-1) RangeError.

ℹ️ prependAllUnsafe has the same tail-unset gap

The prependAllUnsafe function at MutableList.ts:286 (called by prependAll) shares the same structure as the now-fixed prepend: it sets self.head to a new bucket on an empty list but does not set self.tail. A prependAll on an empty list followed by append will therefore still overwrite the prepended bucket.

Technical details
# `prependAllUnsafe` tail initialization

## Affected sites
- `packages/effect/src/MutableList.ts:286-294``prependAllUnsafe` creates a new head bucket without setting `self.tail`, identical to the `prepend` bug before fix

## Required outcome
- Add `if (!self.tail) self.tail = self.head` after `self.head = { ... }` in `prependAllUnsafe`, matching the `prepend` fix

## Open questions for the human
- Widen the changeset description to mention `prependAll` as well, or keep the scope narrow and address in a follow-up?

Pullfrog  | Fix it ➔View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) (Kimi K2 not used — the program covers this model; add its provider key to run your pick) | 𝕏

@github-actions

github-actions Bot commented Aug 1, 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 6.63 KB 6.63 KB 0.00 KB (0.00%)
batching.ts 9.42 KB 9.42 KB 0.00 KB (0.00%)
brand.ts 6.31 KB 6.31 KB 0.00 KB (0.00%)
cache.ts 10.16 KB 10.16 KB 0.00 KB (0.00%)
config.ts 20.32 KB 20.32 KB 0.00 KB (0.00%)
differ.ts 19.93 KB 19.93 KB 0.00 KB (0.00%)
http-client.ts 21.02 KB 21.02 KB 0.00 KB (0.00%)
logger.ts 10.32 KB 10.32 KB 0.00 KB (0.00%)
metric.ts 8.55 KB 8.55 KB 0.00 KB (0.00%)
optic.ts 7.33 KB 7.33 KB 0.00 KB (0.00%)
pubsub.ts 14.47 KB 14.46 KB +0.01 KB (+0.06%)
queue.ts 11.13 KB 11.13 KB 0.00 KB (0.00%)
schedule.ts 10.31 KB 10.31 KB 0.00 KB (0.00%)
schema-class.ts 18.86 KB 18.86 KB 0.00 KB (0.00%)
schema-fromJsonSchemaDocument.ts 28.67 KB 28.67 KB 0.00 KB (0.00%)
schema-representation-roundtrip.ts 24.99 KB 24.99 KB 0.00 KB (0.00%)
schema-string-transformation.ts 12.99 KB 12.99 KB 0.00 KB (0.00%)
schema-string.ts 10.65 KB 10.65 KB 0.00 KB (0.00%)
schema-template-literal.ts 14.85 KB 14.85 KB 0.00 KB (0.00%)
schema-toArbitraryLazy.ts 21.66 KB 21.66 KB 0.00 KB (0.00%)
schema-toCodeDocument.ts 24.08 KB 24.08 KB 0.00 KB (0.00%)
schema-toCodecJson.ts 18.91 KB 18.91 KB 0.00 KB (0.00%)
schema-toEquivalence.ts 18.73 KB 18.73 KB 0.00 KB (0.00%)
schema-toFormatter.ts 18.59 KB 18.59 KB 0.00 KB (0.00%)
schema-toJsonSchemaDocument.ts 22.33 KB 22.33 KB 0.00 KB (0.00%)
schema-toRepresentation.ts 19.25 KB 19.25 KB 0.00 KB (0.00%)
schema.ts 18.12 KB 18.12 KB 0.00 KB (0.00%)
stm.ts 12.11 KB 12.11 KB 0.00 KB (0.00%)
stream.ts 9.37 KB 9.37 KB 0.00 KB (0.00%)

@tim-smart
tim-smart merged commit 8ef7257 into main Aug 2, 2026
18 of 19 checks passed
@tim-smart
tim-smart deleted the audit/repro-core-mutablelist-prepend-tail branch August 2, 2026 00:43
@github-project-automation github-project-automation Bot moved this from Discussion Ongoing to Done in PR Backlog Aug 2, 2026
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

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants