{"record":{"id":"a3c1fc9832e8a19b","repo":"gastownhall/beads","slug":"failed-to-parse-memory-record-w-a3c1fc","errorCode":null,"errorMessage":"failed to parse memory record: %w","messagePattern":"failed to parse memory record: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/import_shared.go","lineNumber":1029,"sourceCode":"\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 {\n\t\t\tvar typeStr string\n\t\t\tif err := json.Unmarshal(rawType, &typeStr); err == nil && typeStr == \"memory\" {\n\t\t\t\tvar mem memoryRecord\n\t\t\t\tif err := json.Unmarshal([]byte(line), &mem); err != nil {\n\t\t\t\t\treturn nil, nil, fmt.Errorf(\"failed to parse memory record: %w\", err)\n\t\t\t\t}\n\t\t\t\tif mem.Key != \"\" && mem.Value != \"\" {\n\t\t\t\t\tconfigEntries[kvPrefix+memoryPrefix+mem.Key] = mem.Value\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\t// Regular issue record\n\t\tvar issue types.Issue\n\t\tif err := json.Unmarshal([]byte(line), &issue); err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"failed to parse issue from JSONL: %w\", err)\n\t\t}\n\t\t// Skip tombstone entries: these are deleted issues exported by older\n\t\t// versions (pre-v0.50) with status \"tombstone\" and deleted_at set.\n\t\t// They are not valid for re-import since \"tombstone\" is not a real status.\n\t\tif issue.Status == \"tombstone\" {\n\t\t\tcontinue","sourceCodeStart":1011,"sourceCodeEnd":1047,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/import_shared.go#L1011-L1047","documentation":"Lines whose peek map has `_type: \"memory\"` are unmarshaled into a memoryRecord struct. If that unmarshal fails (a JSON-valid line whose fields don't match the memory record schema — e.g. wrong types), the import aborts with `failed to parse memory record:` wrapping the json error. This is a schema mismatch, not a JSON syntax problem — line 798's syntax check already passed.","triggerScenarios":"`bd import file.jsonl` containing a line like {\"_type\":\"memory\",...} whose fields have incompatible types (e.g. `key` as a number, nested object where a string is expected) or missing required JSON structure for memoryRecord.","commonSituations":"Hand-crafted memory records with wrong field types; exports from a newer/older bd version with a changed memory schema imported by a mismatched binary; scripts generating memory lines programmatically with unquoted or numeric values.","solutions":["Read the wrapped json.Unmarshal error — it names the offending field and expected type; fix that line's field types.","Compare against a known-good memory line from a `bd export` and correct your record to match the schema.","Ensure the exporting and importing bd versions match; re-export with the current version if schemas differ.","Remove the bad memory line if the memory is unnecessary, and import the issues separately."],"exampleFix":"// before\n{\"_type\":\"memory\",\"key\":\"foo\",\"value\":123}        # value not a string\n// after\n{\"_type\":\"memory\",\"key\":\"foo\",\"value\":\"123\"}    # string value matches memoryRecord","handlingStrategy":"type-guard","validationCode":"func validateMemoryLines(path string) error {\n    data, _ := os.ReadFile(path)\n    for i, line := range strings.Split(string(data), \"\\n\") {\n        var peek map[string]json.RawMessage\n        if json.Unmarshal([]byte(line), &peek) != nil { continue }\n        if t, ok := peek[\"_type\"]; ok && string(t) == `\"memory\"` {\n            var mem struct {\n                Key   string `json:\"key\"`\n                Value string `json:\"value\"`\n            }\n            if err := json.Unmarshal([]byte(line), &mem); err != nil {\n                return fmt.Errorf(\"line %d: %w\", i+1, err)\n            }\n        }\n    }\n    return nil\n}","typeGuard":"func isMemoryRecord(line []byte) (memoryRecord, bool) {\n    var peek map[string]json.RawMessage\n    if json.Unmarshal(line, &peek) != nil { return memoryRecord{}, false }\n    if t, ok := peek[\"_type\"]; !ok || string(t) != `\"memory\"` { return memoryRecord{}, false }\n    var mem memoryRecord\n    if json.Unmarshal(line, &mem) != nil { return memoryRecord{}, false }\n    return mem, true\n}","tryCatchPattern":"if err := importFrom(path); err != nil {\n    if strings.Contains(err.Error(), \"failed to parse memory record\") {\n        return fmt.Errorf(\"memory line field types don't match schema; fix or drop the line: %w\", err)\n    }\n    return err\n}","preventionTips":["Quote all memory record string fields in hand-written JSONL.","Keep exporting and importing bd versions in sync (schema changes).","Generate memory lines from a reference `bd export` instead of from scratch.","Pre-validate `_type:\"memory\"` lines with a struct unmarshal before import."],"tags":["jsonl","schema","memory-record","parsing"],"backgroundTag":"memory-record-schema-mismatch","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}