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)
メンテナーはふだん 1 日以内に返信
@argszero がすでに取り組んでいます。
2026年10月21日 から。
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 67/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 技術スタック
- bun, typescript
- 領域
- backend
調査の方向性
package.json の workspace 依存関係カタログから始め、既存の Effect パッケージのバージョン固定を確認してください。Issue では修正を、upstream 依存関係をバージョン 4.0.5 以降に更新することとしています。workspace のロックファイルと依存関係更新の規約を確認し、解決されたバージョンを検証してください。影響を受ける Effect パッケージが BigInt の dev マッピング修正を含むバージョンに解決されれば完了です。
索引モデルが issue の本文から書いたものです。
説明
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
- 主要言語
- TypeScript
- スター
- 215k
- フォーク
- 28.9k
- 平均マージ
- 8時間 11分
- マージ済み PR(30日)
- 365
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
anomalyco/opencode のほかの issue
-
reproduced
難易度 2/5 1〜3時間 初心者へのやさしさ 67/100
anomalyco/opencode#57711 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
anomalyco/opencode#57698 · コメント 3 件 ·
メンテナーはふだん 1 日以内に返信
-
pending close triaging
難易度 2/5 1〜3時間 初心者へのやさしさ 66/100
anomalyco/opencode#57664 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 74/100
anomalyco/opencode#57579 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
anomalyco/opencode#57536 · コメント 1 件 · リアクション 1 件 ·
メンテナーはふだん 1 日以内に返信
anomalyco/opencode の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 74/100
paperclipai/paperclip#17151 ·
メンテナーはふだん 1 日以内に返信
-
needs-triage
難易度 2/5 1〜3時間 初心者へのやさしさ 83/100
AgoraIO-Extensions/agent-infra#3159 ·
メンテナーはふだん 1 日以内に返信
-
blocklist addition
難易度 1/5 1時間未満 初心者へのやさしさ 66/100
MetaMask/eth-phishing-detect#304596 ·
メンテナーはふだん 1 日以内に返信
-
friction
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
kentcdodds/kody#4142 ·
-
[Bug] Statistics | Task statistics are always empty on MikroORM with MySQL or SQLite対応中かも @NdekoCode が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
ever-co/ever-gauzy#11214 ·
メンテナーはふだん 1 日以内に返信