Skip to content

codemode: TextEncoder.encode(null) silently returns empty bytes #57632

Closed as not planned

Description

@sdivyanshu90

Description

V2 Code Mode silently drops null when encoding text: new TextEncoder().encode(null) returns no bytes instead of the UTF-8 bytes for "null". This changes serialized data when a script encodes a nullable tool result.

textEncoderGlobal in packages/codemode/src/stdlib/bytes.ts uses args[0] ?? "", treating explicit null like an omitted argument. Default only undefined to the empty string, then apply string conversion. This matches the TextEncoder contract.

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"

console.log(await Effect.runPromise(CodeMode.execute({
  code: "return [...new TextEncoder().encode(null)]",
  tools: {},
})))

Observed: successful result with value: [].
Expected: value: [110, 117, 108, 108], matching native TextEncoder. Omitted input and explicit undefined should still produce no bytes.

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). Inside Code Mode, new TextEncoder().encode(null) returns [], but native TextEncoder returns [110, 117, 108, 108]. encode() and encode(undefined) correctly return []. As you found, the cause looks like the args[0] ?? "" in packages/codemode/src/stdlib/bytes.ts, which turns an explicit null into an empty string. The script below reproduces it.

    Reproduction script (repro.ts)
    // Run from an opencode checkout: bun /workspace/repro/repro.ts [/path/to/repo]
    import { Effect } from "effect"
    const repo = process.argv[2] ?? process.env.OC_DEV ?? "/workspace/repo"
    const { CodeMode } = await import(`${repo}/packages/codemode/src/index.ts`)
    
    for (const code of [
      "return [...new TextEncoder().encode(null)]",
      "return [...new TextEncoder().encode()]",
      "return [...new TextEncoder().encode(undefined)]",
    ]) {
      const r = await Effect.runPromise(CodeMode.execute({ code, tools: {} }))
      console.log(code, "=>", JSON.stringify(r.value ?? r))
    }
    const native = (v: any) => [...new TextEncoder().encode(v)]
    console.log("native null =>", JSON.stringify(native(null)), " native undefined =>", JSON.stringify(native(undefined)))

    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: encode(null) preserves the text "null", while omitted input and undefined still produce empty bytes. 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

    im not looking to endlessly make the interpreter handle every edge case in javascript, it's a tool orchestration environment, unless ur seeing agents write code that breaks then i dont rlly want more of these styles of issues opened ideally

    Not sure if u actually hit this or if u just have agents looking to find issues, but this seems like edge case

  4. sdivyanshu90 commented on Oct 21, 2026

    @sdivyanshu90
    ContributorAuthor

    Thanks for clarifying, @rekram1-node. These reports came from compatibility testing, not failures I encountered in an actual agent workflow. I should have made that distinction clear.

    I’ll leave #57633 closed, and I’m happy to close #57632 as well. Going forward, I’ll focus on issues with demonstrated impact on real V2 workflows. Thanks for the guidance.

  5. rekram1-node commented on Oct 21, 2026

    @rekram1-node
    Collaborator

    sounds good ill close this for now then thanks.

    Ideally don't look for issues, instead raise problems u actually hit. Otherwise it's a lot of noise for us.

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