{"record":{"id":"0ceb580217d8d872","repo":"gastownhall/beads","slug":"failed-to-parse-jsonl-line-w-0ceb58","errorCode":null,"errorMessage":"failed to parse JSONL line: %w","messagePattern":"failed to parse JSONL line: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/import_shared.go","lineNumber":1006,"sourceCode":"\t\treturn nil, nil, fmt.Errorf(\"failed to read JSONL file %s: %w\", path, err)\n\t}\n\n\tscanner := bufio.NewScanner(strings.NewReader(string(data)))\n\t// Allow up to 64MB per line for large descriptions\n\tscanner.Buffer(make([]byte, 0, 1024*1024), 64*1024*1024)\n\tvar issues []*types.Issue\n\tconfigEntries := make(map[string]string)\n\n\tfor scanner.Scan() {\n\t\tline := scanner.Text()\n\t\tif line == \"\" {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Peek at the record to check for _type field\n\t\tvar peek map[string]json.RawMessage\n\t\tif err := json.Unmarshal([]byte(line), &peek); err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"failed to parse JSONL line: %w\", err)\n\t\t}\n\n\t\t// Skip the optional beads-jsonl metadata/header record.\n\t\t// Canonical exports produced by the stable-ordering /\n\t\t// git-merge convention prepend a schema+provenance line, e.g.\n\t\t// {\"_schema\":\"beads-jsonl/1\",\"_dolt_branch\":\"main\",\n\t\t// \"_dolt_commit\":\"...\",\"_sort\":\"stable-v1\"}. It carries no\n\t\t// _type and no issue fields; without this guard it falls\n\t\t// through to the issue path, unmarshals into an empty Issue,\n\t\t// and aborts the whole import with \"validation failed for\n\t\t// issue : title is required\". Identified by the _schema\n\t\t// sentinel, which real issue/memory records never carry.\n\t\tif _, isHeader := peek[\"_schema\"]; isHeader {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Check if this is a memory record\n\t\tif rawType, ok := peek[\"_type\"]; ok {","sourceCodeStart":988,"sourceCodeEnd":1024,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/import_shared.go#L988-L1024","documentation":"After reading the file, parseJSONLFile unmarshals each non-empty line first into a peek map (map[string]json.RawMessage) to inspect the `_type` field. If any line is not valid JSON, the parse fails with `failed to parse JSONL line:` wrapping the json error. Every line of a JSONL file must be a complete, standalone JSON object.","triggerScenarios":"`bd import file.jsonl` where a line contains malformed JSON: truncated writes, hand-edited lines with syntax errors, concatenated exports (two objects on one line), binary corruption, or smart-quote/copy-paste artifacts.","commonSituations":"A partially downloaded or interrupted export file; manual edits to issue descriptions breaking quoting/escaping; merging export files with a tool that didn't preserve line-per-record format; a git merge conflict marker left inside the file.","solutions":["The error names the line offset/cause — open the file at that line and fix or remove the malformed line.","Validate the whole file: `while IFS= read -r l; do echo \"$l\" | jq empty || echo BAD; done < file.jsonl` (or `jq -s . file.jsonl`).","Re-export from the source (`bd export -o file.jsonl`) instead of hand-repairing a corrupted copy.","Check for git merge-conflict markers or duplicated/concatenated lines if the file was merged or concatenated."],"exampleFix":"// before (file line 42)\n{\"id\":\"bd-42\" \"title\":\"broken\"}        # missing comma\n// after\n{\"id\":\"bd-42\",\"title\":\"broken\"}        # valid JSON, or re-export via bd export","handlingStrategy":"validation","validationCode":"func validateJSONL(path string) error {\n    f, err := os.Open(path)\n    if err != nil { return err }\n    defer f.Close()\n    sc := bufio.NewScanner(f)\n    for i := 1; sc.Scan(); i++ {\n        line := strings.TrimSpace(sc.Text())\n        if line == \"\" { continue }\n        if err := json.Unmarshal([]byte(line), new(map[string]json.RawMessage)); err != nil {\n            return fmt.Errorf(\"line %d: %w\", i, err)\n        }\n    }\n    return sc.Err()\n}\n// run validateJSONL(path) before bd import","typeGuard":"func isJSONObject(line []byte) bool {\n    var m map[string]json.RawMessage\n    return json.Unmarshal(line, &m) == nil\n}","tryCatchPattern":"if err := importFrom(path); err != nil {\n    if strings.Contains(err.Error(), \"failed to parse JSONL line\") {\n        return fmt.Errorf(\"malformed JSONL; validate with `jq empty` per line, or re-export: %w\", err)\n    }\n    return err\n}","preventionTips":["Always re-export with `bd export -o file.jsonl` instead of hand-editing exports.","Never concatenate JSONL exports without guaranteeing one object per line.","Check for git merge-conflict markers in shared export files.","Validate each line with `jq empty` before importing."],"tags":["jsonl","parsing","import","json"],"backgroundTag":"jsonl-parse-error","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}