gastownhall/beads · error

failed to read JSONL file %s: %w

Error message

failed to read JSONL file %s: %w

What it means

parseJSONLFile reads the import file from disk before any parsing. If os.ReadFile fails (missing file, permission denied, path is a directory, I/O error), the import aborts with `failed to read JSONL file <path>: <cause>`. This is a pre-parse, filesystem-level failure — the JSON content itself is never examined.

Source

Thrown at cmd/bd/import_shared.go:988

// importFromLocalJSONL imports issues (and memories) from a local JSONL file on disk
// into the Dolt store. Returns the number of issues imported and any error.
// This is a convenience wrapper around importFromLocalJSONLFull.
func importFromLocalJSONL(ctx context.Context, store storage.DoltStorage, localPath string) (int, error) {
	result, err := importFromLocalJSONLFull(ctx, store, localPath)
	if err != nil {
		return 0, err
	}
	return result.Issues, nil
}

// parseJSONLFile reads a JSONL file and returns parsed issues and config
// entries (memories). Pure function — no store I/O.
func parseJSONLFile(path string) ([]*types.Issue, map[string]string, error) {
	//nolint:gosec // G304: path from user-provided CLI argument
	data, err := os.ReadFile(path)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to read JSONL file %s: %w", path, err)
	}

	scanner := bufio.NewScanner(strings.NewReader(string(data)))
	// Allow up to 64MB per line for large descriptions
	scanner.Buffer(make([]byte, 0, 1024*1024), 64*1024*1024)
	var issues []*types.Issue
	configEntries := make(map[string]string)

	for scanner.Scan() {
		line := scanner.Text()
		if line == "" {
			continue
		}

		// Peek at the record to check for _type field
		var peek map[string]json.RawMessage
		if err := json.Unmarshal([]byte(line), &peek); err != nil {
			return nil, nil, fmt.Errorf("failed to parse JSONL line: %w", err)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Verify the path exists and is readable: `ls -la <path>` and check you're in the intended working directory.
  2. Use an absolute path or correct the relative path.
  3. Fix file permissions (`chmod u+r`) or re-export the JSONL from the source repository.
  4. If a script does the export-then-import, ensure the export step succeeded before importing.

Example fix

// before
bd import export.jsonl   # failed to read JSONL file export.jsonl: no such file or directory
// after
ls -la; bd import /absolute/path/to/export.jsonl   # correct, existing path
Defensive patterns

Strategy: validation

Validate before calling

func requireReadableJSONL(path string) error {
    fi, err := os.Stat(path)
    if err != nil { return err }
    if fi.IsDir() { return fmt.Errorf("%s is a directory", path) }
    f, err := os.Open(path)
    if err != nil { return err }
    return f.Close()
}
// call requireReadableJSONL(path) before bd import

Try / catch

if err := runImport(path); err != nil {
    if strings.Contains(err.Error(), "failed to read JSONL file") {
        return fmt.Errorf("check the import path (exists? readable? correct cwd): %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: `bd import path.jsonl` where the file doesn't exist, the path is wrong relative to the current directory, the file lacks read permissions, or the path points to a directory instead of a file.

Common situations: Typo in filename or running from a different working directory; file deleted or renamed after a previous export; exporting to a path and importing a stale/incorrect path in scripts; permissions changed by a sync/backup tool.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/dc358820847e1af2. Report an issue: GitHub.