gastownhall/beads · error
failed to scan JSONL: %w
Error message
failed to scan JSONL: %w
What it means
After parsing all lines of a JSONL file, parseJSONLFile checks bufio.Scanner.Err(). This error fires when the underlying reader itself failed (I/O error reading the file), as opposed to a per-line JSON problem — a distinct failure from the line-parse errors.
Source
Thrown at cmd/bd/import_shared.go:1056
// Regular issue record
var issue types.Issue
if err := json.Unmarshal([]byte(line), &issue); err != nil {
return nil, nil, fmt.Errorf("failed to parse issue from JSONL: %w", err)
}
// Skip tombstone entries: these are deleted issues exported by older
// versions (pre-v0.50) with status "tombstone" and deleted_at set.
// They are not valid for re-import since "tombstone" is not a real status.
if issue.Status == "tombstone" {
continue
}
applyImportWispPlane(peek, &issue)
issue.SetDefaults()
issues = append(issues, &issue)
}
if err := scanner.Err(); err != nil {
return nil, nil, fmt.Errorf("failed to scan JSONL: %w", err)
}
return issues, configEntries, nil
}
// applyImportWispPlane resolves which storage plane (wisps vs issues table) a
// parsed import record routes to, shared by every JSONL parse loop
// (parseImportRecords for `bd import` in both storage modes, parseJSONLFile
// for bootstrap / init --from-jsonl / auto-import).
//
// The "wisp_plane" peek key is the EXPLICIT wisps-plane marker (bd-r9uce):
// export writes it for rows that live in the wisps table, precisely because
// row flags cannot be trusted for the plane decision — a promoted no-history
// wisp is a durable issues-table row that may still carry no_history=true
// (PromoteFromEphemeralInTx used to clear only Ephemeral, and wild data
// with that shape persists). Routing such a record by flags re-planes it
// into the wisps table, after which its cross-plane relations are dropped
// by the batch import and the row itself is no longer durable — silent dataView on GitHub (pinned to 71377f2769)
Solutions
- Re-run the command — transient I/O errors (network mount blips) often clear on retry
- Verify the file exists and is readable: `ls -l .beads/issues.jsonl && head -1 .beads/issues.jsonl`
- Check filesystem/mount health (dmesg for I/O errors; remount the network share)
- Regenerate the JSONL with `bd export` if the file is damaged, then re-import
Defensive patterns
Strategy: retry
Validate before calling
f, err := os.Open(path)
if err != nil { return err }
st, err := f.Stat()
if err != nil { return err }
if !st.Mode().IsRegular() { return fmt.Errorf("%s is not a regular file", path) }
f.Close() Try / catch
if _, _, err := parseJSONLFile(path); err != nil {
if strings.Contains(err.Error(), "failed to scan JSONL") {
// transient I/O: back off and retry
time.Sleep(2 * time.Second)
return parseJSONLFile(path)
}
return err
} Prevention
- Keep .beads/ off flaky network mounts or wait for sync tools (Dropbox/Drive) to settle
- Avoid reading the JSONL while another process is rewriting it
- Monitor disk health if I/O errors recur
- Use local filesystem storage for Dolt data
When it happens
Trigger: During parseJSONLFile (auto-import, bootstrap, init --from-jsonl), the scanner reading the JSONL file hits an I/O error: the file was deleted/truncated mid-read, the filesystem returned EIO, a network mount dropped, or the path is a special file that errors on read.
Common situations: .beads/issues.jsonl lives on an NFS/cloud-synced folder that disconnected mid-import; the file was replaced or truncated while `bd` ran; disk errors or permissions changing mid-read; reading a FIFO/device that errored.
Related errors
- failed to read JSONL: %w
- failed to read JSONL file %s: %w
- failed to parse JSONL line: %w
- failed to parse issue from JSONL: %w
- --from-jsonl specified but %s does not exist
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/2b784a5100b0313a.
Report an issue: GitHub.