Skip to content

codemode: Uint8Array constructor rejects valid fractional and NaN lengths #57633

Closed as not planned

Description

@sdivyanshu90

Description

V2 Code Mode rejects valid typed-array lengths. For example, new Uint8Array(1.9) throws instead of allocating one zero byte, and new Uint8Array(NaN) throws instead of returning an empty array. Scripts calculating a buffer size or converting an input to a number can fail despite working in JavaScript.

constructBytes in packages/codemode/src/stdlib/bytes.ts checks Number.isInteger before truncating the length. Apply the existing integer conversion helper before validation, keeping the allocation limit. The TypedArray constructor uses ToIndex, which truncates fractions and maps NaN to zero.

Plugins

None required.

OpenCode version

V2 development checkout; @opencode/codemode 2.1.2.

Steps to reproduce

Save this as repro.ts in packages/codemode and run bun repro.ts:

import { Effect } from "effect"
import { CodeMode } from "./src/index.js"

for (const input of ["1.9", "-0.9", "NaN", '"2.9"']) {
  console.log(input, await Effect.runPromise(CodeMode.execute({
    code: `return [...new Uint8Array(${input})]`,
    tools: {},
  })))
}

Observed: every case fails with RangeError: Invalid typed array length.
Expected: [0], [], [], and [0, 0], respectively. Native JavaScript produces those values. Negative integer lengths and infinities should continue to throw.

Screenshot

Not applicable; interpreter behavior.

Operating System

Linux, Bun 1.4.3.

Terminal

Bash.

Activity

  1. opencode-agent commented on Oct 21, 2026

    @opencode-agent
    Contributor

    Thanks for the clear report. I reproduced this on the latest dev (c9b5a9f, @opencode/codemode 2.1.2).

    In Code Mode, new Uint8Array(1.9), new Uint8Array(-0.9), new Uint8Array(NaN) and new Uint8Array("2.9") all fail with RangeError: Invalid typed array length: …. Native JavaScript returns [0], [], [] and [0, 0]. Negative integers and ±Infinity correctly throw in both. The script below runs each case through CodeMode.execute and compares it with native JS.

    As you said, constructBytes in packages/codemode/src/stdlib/bytes.ts rejects lengths that aren't integers instead of truncating them first.

    Reproduction script (repro.ts)
    // Run from packages/codemode of an opencode dev checkout: bun /workspace/repro/repro.ts
    // (or set CODEMODE_DIR to the packages/codemode directory)
    const dir = process.env.CODEMODE_DIR ?? process.cwd()
    const { Effect } = await import(Bun.resolveSync("effect", dir))
    const { CodeMode } = await import(`${dir}/src/index.js`)
    
    const cases: Array<[string, string]> = [
      ["1.9", "[0]"], ["-0.9", "[]"], ["NaN", "[]"], ['"2.9"', "[0,0]"],
      ["-1", "RangeError"], ["Infinity", "RangeError"], ["-Infinity", "RangeError"],
    ]
    for (const [input, expected] of cases) {
      const native = (() => { try { return JSON.stringify([...new Uint8Array(eval(input))]) } catch (e) { return String((e as Error).name) } })()
      const result = await Effect.runPromise(
        CodeMode.execute({ code: `return [...new Uint8Array(${input})]`, tools: {} }),
      ).catch((e) => ({ thrown: String(e) }))
      console.log(`new Uint8Array(${input})  expected=${expected} native=${native}  codemode=${JSON.stringify(result)}`)
    }

    Run it: bun repro.ts

  2. sdivyanshu90 commented on Oct 21, 2026

    @sdivyanshu90
    ContributorAuthor

    Hi @rekram1-node, I'd like to claim this issue. I've prepared a fix with regression tests: constructor lengths are normalized before validation, so fractions truncate and NaN becomes zero. Negative integer lengths, infinities, and oversized allocations still fail. The full CodeMode suite and package typecheck pass.

    Could you please review the proposed fix when you have some time? I can raise a PR, but GitHub currently blocks creation with: "You've reached this repository's open pull request limit." I'll open it once a slot is available. Thanks!

  3. rekram1-node commented on Oct 21, 2026

    @rekram1-node
    Collaborator
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions