anomalyco / anomalyco/opencode

Native crash (SIGTRAP) in fff-scan thread during watcher resubscribe after scan — FileItem::write_absolute_path overflows fixed 1024-byte buffer (macOS arm64)

Open
#43,356 1 comment 0 reactions 1 assignee View on GitHub

@kitlangton is already working on this.

Since Aug 19, 2026.

Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

Description

Summary

opencode crashes with a native Rust panic in the bundled fff file-indexer during a scan, killing the whole process with no error in opencode.log.

  • opencode: 1.18.18 (latest at time of filing)
  • Platform: macOS 26.5.2, Apple Silicon (arm64)
  • Crash reports: ~/Library/Logs/DiagnosticReports/opencode-2026-08-18-210957.ips and opencode-2026-08-18-222412.ips — two crashes ~75 min apart, byte-identical faulting stack.

Crash signature

EXC_BREAKPOINT / SIGTRAP
faultingThread: 33, thread name: "fff-scan"

fff_search::types::FileItem::write_absolute_path::h6be4aaca40dafd85
fff_search::scan::rescubscribe_watcher_post_scan::hd9b19e5fc8d2229e
fff_search::scan::ScanJob::run::hb82750f8c22d9326
std::sys::backtrace::__rust_begin_short_backtrace
core::ops::function::FnOnce::call_once{{vtable.shim}}
std::sys::thread::Thread::new::thread_start

What was happening

Both crashes occurred during long agentic sessions in a git repo with multiple worktrees (jot-brain, jot-brain-wt119, jot-brain-wtsec). The app log shows the session running a rescan loop and stopping abruptly mid-step with no error line:

...loop session.id=ses_... step=243
[trace/breakpoint trap]  ← process dies here, nothing logged

Root cause hypothesis (from fff source)

The panic is in FileItem::write_absolute_path (fff-core/src/types.rs), which writes base_path + '/' + relative_path into a fixed-size stack buffer:

#[cfg(not(target_os = "windows"))]
pub const PATH_BUF_SIZE: usize = libc::PATH_MAX as usize;   // 1024 on macOS

pub(crate) fn write_absolute_path<'a>(&self, arena, base_path, buf: &'a mut [u8; PATH_BUF_SIZE]) {
    let base_len = base.len();
    buf[..base_len].copy_from_slice(base);          // panics if base_len > 1024
    ...
    buf[base_len] = std::path::MAIN_SEPARATOR as u8; // panics if base_len == 1024
    ...
}

There is no bounds check. During ScanJob::runrescubscribe_watcher_post_scan (fff-core/src/scan.rs), the watcher is re-subscribed to every indexed directory; any directory path ≥ PATH_BUF_SIZE (1024 on macOS) causes a slice index out of range Rust panic.

Rust panics in the native lib abort the process via an int3 trap → recorded by macOS as EXC_BREAKPOINT/SIGTRAP, and bypass the opencode JS logger, so the app log just ends mid-loop with no error. The two identical .ips files confirm a deterministic trigger rather than two unrelated incidents.

Related

  • #42557 — fff watcher / libgit2 busy-loop (same fff code area)
  • #32511, #35791, #37740 — fff over-indexing / watch explosion
  • #31682, #31747, #31701, #31850 — earlier (closed) fff scan crashes in 1.17.x

Ask

  • Bounds-check the path write in write_absolute_path (fall back to heap PathBuf when PATH_BUF_SIZE is exceeded).
  • Consider raising PATH_BUF_SIZE / not truncating silently.

Crash reports available on request.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.