fs: /cd and file pickers fail on FreeBSD/ZFS — `stat` throws "dev exceeds the safe integer range" (fixed in @effect/platform-node-shared 4.0.5)
Maintainers usually reply within 1 day
@argszero is already working on this.
Since Oct 21, 2026.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 67/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- bun, typescript
- Domain
- backend
Research direction
Start with the workspace dependency catalog in package.json and check the existing Effect package version pins. The issue identifies the fix as an upstream dependency update to 4.0.5 or later; review the workspace lockfile and dependency update conventions, then verify the resolved versions. Done means the affected Effect packages resolve to a version containing the BigInt dev mapping fix.
Written by the indexing model from the issue text.
Description
Description
Summary
OpenCode's Node filesystem layer comes from @effect/platform-node-shared, whose stat calls fs.stat(path, { bigint: true }) and then converts the BigInt dev field to a Number, throwing a RangeError when the value is outside the safe-integer range. FreeBSD reports 64-bit st_dev values for ZFS datasets (e.g. 8599779474788709465), so stat fails for essentially every path on the host. The visible result is that GET /api/fs/list, /api/fs/find, and /api/fs/read return HTTP 500, POST /api/session/{id}/move answers "Directory does not exist" for directories that do exist, and the TUI /cd command is unusable.
Effect already fixed this upstream in @effect/platform-node-shared 4.0.5 (https://github.com/Effect-TS/effect/pull/9112), which keeps dev as a BigInt. OpenCode still pins 4.0.1 in its workspace catalog, in v2.0.32, in v2.1.1, and on dev.
Environment
- opencode version: 2.0.32 (channel: latest)
- OS: FreeBSD 15.1-RELEASE (freebsd x64), ZFS 2.4.2-1-FreeBSD_g6330a45b0 (root dataset
zroot/ROOT/15.1-RELEASE/usr/homeonzroot/usr/home`) - Bun (embedded in the opencode binary): v1.4.2 (744846f84) FreeBSD x64
- Terminal: TERM=xterm-256color, TERM_PROGRAM=tmux, COLORTERM=truecolor
- Shell: /usr/local/bin/bash
- Install/channel: release (
latest) - Active plugins: none found (
opencode plugin list→ "No plugins found"); noopencode.json/opencode.jsonc/cli.jsonpresent - Pinned dependency:
"@effect/platform-node": "4.0.1","@effect/platform-node-shared": "4.0.1","effect": "4.0.1"(workspace catalog inpackage.json)
Reproduction
- Run OpenCode on a FreeBSD host whose working directory is on a ZFS dataset.
- In the TUI, type
/cdand keep typing a path. - Observe:
Could not search directories. Keep typing to try again.The dropdown stays empty, and Enter is swallowed by the autocomplete handler, so the command cannot be submitted. - The same failure occurs server-side when the move is issued directly:
$ opencode api post /api/session/<id>/move --data '{"directory":"/usr/home/asomers/src/github"}'
{"_tag":"InvalidRequestError","message":"Directory does not exist: /usr/home/asomers/src/github"}
- The directory listing endpoints fail with HTTP 500:
$ opencode api get "/api/fs/list?path=/usr/home/asomers&location.directory=/usr/home/asomers"
HTTP 500 Internal Server Error
$ opencode api get "/api/fs/find?query=src&limit=5&location.directory=/usr/home/asomers"
HTTP 500 Internal Server Error
$ opencode api get "/api/fs/read//usr/home/asomers/.profile"
HTTP 500 Internal Server Error
/usr/home/asomers/src/github exists (drwxr-xr-x 28 asomers asomers 29 Aug 7 14:40), so the "Directory does not exist" response is a false negative.
Expected Behavior
GET /api/fs/listreturns the children of the requested directory.POST /api/session/{id}/movemoves the session to the requested directory.- In the TUI,
/cd <path>lists matching directories and changes the session's working directory.
Actual Behavior
The filesystem layer throws before producing a result:
PlatformError: FileSystem.stat: dev exceeds the safe integer range: 8599779474788709465
at Ec (/$bunfs/root/chunk-6xc3bwx4.js:2:980)
at <anonymous> (/$bunfs/root/chunk-79zk6hn4.js:18:6249)
at FileSystem.list (/$bunfs/root/chunk-26fat8ct.js:449:16850)
at ServerProcess.start (/$bunfs/root/chunk-sz35r0mr.js:2:7534)
Root Cause
The throwing code is not in the OpenCode repository and not in the Bun runtime. It comes from @effect/platform-node-shared, in packages/platform/node-shared/src/NodeFileSystem.ts of https://github.com/Effect-TS/effect (tag [email protected]):
// packages/platform/node-shared/src/NodeFileSystem.ts:37
const bigintToNumber = (value: bigint, field: string): number => {
const number = Number(value)
if (!Number.isSafeInteger(number)) {
throw new RangeError(`${field} exceeds the safe integer range: ${value}`)
}
return number
}
// packages/platform/node-shared/src/NodeFileSystem.ts:533
dev: bigintToNumber(stat.dev, "dev"),
rdev: bigintToNumberOption(stat.rdev),
ino: bigintToNumberOption(stat.ino),
mode: bigintToNumber(stat.mode, "mode"),
stat requests { bigint: true } and maps the fields back. dev and mode go through the strict bigintToNumber, which throws; the other fields use bigintToNumberOption, which returns undefined instead of throwing. dev is the field that breaks on FreeBSD/ZFS.
Relevant st_dev values on the affected host:
| Path | Filesystem | st_dev |
|---|---|---|
/usr/home |
zroot/usr/home | 8599779474788709465 (throws) |
/usr/local |
zroot/usr/local | 17163752400735175193 (throws) |
/tmp |
zroot/var/tmp | 10799770302823152918 (throws) |
/dev |
devfs | 1895890688 (works) |
/dev succeeds, which is consistent with the diagnosis: only filesystems whose device ID exceeds 2^53−1 are affected.
Already fixed upstream in Effect
Effect PR https://github.com/Effect-TS/effect/pull/9112 changed the mapping in @effect/platform-node-shared 4.0.5:
dev: toUint64(stat.dev),
rdev: toUint64Option(stat.rdev),
Verified against the standalone packages ([email protected], @effect/[email protected]) on the same host:
import { NodeFileSystem } from "@effect/platform-node"
import { Effect } from "effect"
import { FileSystem } from "effect/FileSystem"
const program = Effect.gen(function* () {
const fs = yield* FileSystem
console.log(yield* fs.stat("/usr/home/asomers"))
})
Effect.runPromise(program.pipe(Effect.provide(NodeFileSystem.layer)))
stat OK: { type: "Directory", ..., dev: 8599779474788709465n, ... }
stat succeeds and dev is returned as an exact BigInt. The same script against @effect/[email protected] throws RangeError: dev exceeds the safe integer range: 8599779474788709465.
Versions are affected as follows:
@effect/platform-node-shared |
dev mapping |
|---|---|
| 4.0.0 – 4.0.4 | bigintToNumber(stat.dev, "dev") (throws) |
| 4.0.5 | toUint64(stat.dev) (fixed) |
Additional Context
- Impact surface on the affected host:
- TUI
/cddirectory autocomplete: broken ("Could not search directories. Keep typing to try again.") - TUI
@file autocomplete: broken ("Could not search files. Keep typing to try again.") POST /api/session/{id}/move: broken with a misleading "Directory does not exist" errorGET /api/fs/readon an existing file: HTTP 500- Session creation in a ZFS directory still works (
POST /api/sessionwithlocation.directory), soopencode <dir>is unaffected - The agent's
read/grep/glob/shelltools still work; they do not use the affected endpoints
- TUI
- Suggested change: bump the workspace catalog to
@effect/platform-node/@effect/platform-node-shared/effect4.0.5or later, which picks up the upstream Effect fix. A dependency bump is sufficient; no OpenCode code change is needed. - Reproduces consistently on every request; it is not intermittent.
- Workaround used on this host: start OpenCode in the target directory (
opencode ~/src) or create a session there via the API (POST /api/sessionwithlocation.directory) instead of using/cd.
Plugins
None
OpenCode version
v2.0.32
Steps to reproduce
No response
Screenshot
No response
Operating System
FreeBSD 15.1 amd64
Terminal
Wezterm
- Dominant language
- TypeScript
- Stars
- 215k
- Forks
- 28.9k
- Avg merge
- 4h 21m
- Merged PRs (30d)
- 476
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from anomalyco/opencode
-
desktop: maximized state lost when saved bounds exceed the displayPossibly taken A pull request linked to this issue is open or already merged. Openreproduced
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
anomalyco/opencode#58247 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
anomalyco/opencode#58216 · 1 comment ·
Maintainers usually reply within 1 day
-
pending close triaging
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
anomalyco/opencode#58181 · 1 comment ·
Maintainers usually reply within 1 day
-
Opencde Github Actions Bot Cannot InstallPossibly taken @zzz-creator claimed this today. Openreproduced
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
anomalyco/opencode#57911 · 2 comments ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
anomalyco/opencode#57855 · 1 comment ·
Maintainers usually reply within 1 day
All issues in anomalyco/opencode
Similar issues
-
bug hacktoberfest help wanted
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
libredb/libredb-studio#1941 ·
Maintainers usually reply within 1 day
-
chore other
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
alastair-smith/card-games#308 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 86/100
paperclipai/paperclip#17379 ·
Maintainers usually reply within 1 day
-
[good first issue, hacktoberfest] 🏯 Hacktoberfest Task - Add new Anime Quote 626 (good-first-issue)Opencommunity first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Difficulty 1/5 Under an hour Newbie friendliness 76/100
lingdojo/kana-dojo#33040 · 1 comment · 5 reactions ·
Maintainers usually reply within 1 day
-
bug mobile ui
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
Maintainers usually reply within 1 day