Skip to content

Commit b39c261

Browse files
committed
fix(db): treat a missing events log as empty, not an error
rebuild_state/ingest_new_events opened the project's events JSONL with no guard, so the FIRST journal touch in a brand-new project (e.g. a fresh git worktree) crashed with 'No such file or directory' — which surfaced as task_create failing inside a freshly-spawned agent session. A missing log simply means zero events: return Ok(0) on NotFound.
1 parent 0c4be25 commit b39c261

1 file changed

Lines changed: 28 additions & 4 deletions

File tree

crates/tj-core/src/db.rs

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -329,8 +329,14 @@ pub fn rebuild_state(
329329
jsonl_path: impl AsRef<Path>,
330330
project_hash: &str,
331331
) -> anyhow::Result<usize> {
332-
let f = std::fs::File::open(&jsonl_path)
333-
.with_context(|| format!("open {:?}", jsonl_path.as_ref()))?;
332+
let f = match std::fs::File::open(&jsonl_path) {
333+
Ok(f) => f,
334+
// A fresh project has no events log on disk yet — there is simply nothing
335+
// to read, which is not an error (this is what crashed task_create the
336+
// first time the journal was touched in a new worktree).
337+
Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Ok(0),
338+
Err(e) => return Err(anyhow::Error::new(e).context(format!("open {:?}", jsonl_path.as_ref()))),
339+
};
334340
let reader = std::io::BufReader::new(f);
335341

336342
let tx = conn.unchecked_transaction()?;
@@ -791,8 +797,14 @@ pub fn ingest_new_events(
791797
None => return rebuild_state(conn, jsonl_path, project_hash),
792798
};
793799

794-
let f = std::fs::File::open(&jsonl_path)
795-
.with_context(|| format!("open {:?}", jsonl_path.as_ref()))?;
800+
let f = match std::fs::File::open(&jsonl_path) {
801+
Ok(f) => f,
802+
// A fresh project has no events log on disk yet — there is simply nothing
803+
// to read, which is not an error (this is what crashed task_create the
804+
// first time the journal was touched in a new worktree).
805+
Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Ok(0),
806+
Err(e) => return Err(anyhow::Error::new(e).context(format!("open {:?}", jsonl_path.as_ref()))),
807+
};
796808
let reader = std::io::BufReader::new(f);
797809

798810
// First pass: confirm the marker still exists in the file. If it does
@@ -2063,6 +2075,18 @@ mod tests {
20632075
assert_eq!(n, 2);
20642076
}
20652077

2078+
#[test]
2079+
fn rebuild_state_treats_a_missing_jsonl_as_empty() {
2080+
// A brand-new project has no events log on disk yet — rebuild/ingest must
2081+
// report zero events, not error. This is the crash that made task_create
2082+
// fail the first time the journal was touched in a fresh worktree.
2083+
let d = TempDir::new().unwrap();
2084+
let conn = open(d.path().join("s.sqlite")).unwrap();
2085+
let missing = d.path().join("does-not-exist.jsonl");
2086+
assert_eq!(rebuild_state(&conn, &missing, "deadbeefdeadbeef").unwrap(), 0);
2087+
assert_eq!(ingest_new_events(&conn, &missing, "deadbeefdeadbeef").unwrap(), 0);
2088+
}
2089+
20662090
#[test]
20672091
fn index_event_writes_index_and_fts() {
20682092
let d = TempDir::new().unwrap();

0 commit comments

Comments
 (0)