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)
Maintainer thường phản hồi trong vòng 1 ngày
@argszero đang làm issue này rồi.
Từ ngày 21/10/2026.
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 67/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- bun, typescript
- Lĩnh vực
- backend
Hướng nghiên cứu
Bắt đầu với danh mục dependency của workspace trong package.json và kiểm tra các phiên bản được ghim hiện có của những package Effect. Issue xác định cách khắc phục là cập nhật dependency upstream lên phiên bản 4.0.5 trở lên; xem lại lockfile của workspace và quy ước cập nhật dependency, sau đó xác minh các phiên bản được phân giải. Công việc hoàn tất khi các package Effect bị ảnh hưởng được phân giải thành phiên bản có bản sửa lỗi ánh xạ dev của BigInt.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
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
- Ngôn ngữ chính
- TypeScript
- Star
- 215k
- Fork
- 28.9k
- Merge trung bình
- 6 giờ 8 phút
- Pull request đã merge (30 ngày)
- 411
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của anomalyco/opencode
-
pending close triaging
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
anomalyco/opencode#57939 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
reproduced
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
anomalyco/opencode#57911 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
pending close triaging
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
anomalyco/opencode#57907 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
anomalyco/opencode#57855 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
opencode api truncates large output when stdout is a pipe (un-awaited write before process.exit)Đang mởpending close triaging
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
anomalyco/opencode#57816 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của anomalyco/opencode
Issue tương tự
-
native
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
prime-radiant-inc/evener#4839 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug needs-triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
processone/fluux-messenger#1790 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
🛣️ Infrastructure
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
opencrvs/opencrvs-core#14232 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
kunchenguid/gh-axi#220 ·
Maintainer thường phản hồi trong vòng 1 ngày