{"record":{"id":"dfb699959d9c7c4a","repo":"gastownhall/beads","slug":"marshaling-linear-milestone-metadata-w","errorCode":null,"errorMessage":"marshaling Linear milestone metadata: %w","messagePattern":"marshaling Linear milestone metadata: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/linear.go","lineNumber":706,"sourceCode":"\t}\n\n\tlinearMeta, _ := data[\"linear\"].(map[string]interface{})\n\tif linearMeta == nil {\n\t\tlinearMeta = make(map[string]interface{})\n\t}\n\tlinearMeta[\"kind\"] = \"project_milestone\"\n\tlinearMeta[\"project_milestone\"] = map[string]interface{}{\n\t\t\"id\":          strings.TrimSpace(ms.ID),\n\t\t\"name\":        ms.Name,\n\t\t\"description\": ms.Description,\n\t\t\"progress\":    ms.Progress,\n\t\t\"targetDate\":  ms.TargetDate,\n\t}\n\tdata[\"linear\"] = linearMeta\n\n\traw, err := json.Marshal(data)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"marshaling Linear milestone metadata: %w\", err)\n\t}\n\treturn json.RawMessage(raw), nil\n}\n\nfunc issueHasLinearMilestoneID(issue *types.Issue, milestoneID string) bool {\n\tif issue == nil || len(issue.Metadata) == 0 {\n\t\treturn false\n\t}\n\tvar data struct {\n\t\tLinear struct {\n\t\t\tKind             string `json:\"kind\"`\n\t\t\tProjectMilestone struct {\n\t\t\t\tID string `json:\"id\"`\n\t\t\t} `json:\"project_milestone\"`\n\t\t} `json:\"linear\"`\n\t}\n\tif err := json.Unmarshal(issue.Metadata, &data); err != nil {\n\t\treturn false","sourceCodeStart":688,"sourceCodeEnd":724,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/linear.go#L688-L724","documentation":"After merging the existing metadata with the Linear milestone fields (title, targetDate, etc.), the function re-serializes the map with json.Marshal. Marshaling a map[string]interface{} built from valid values essentially never fails in Go unless a value contains an unsupported type (e.g. a channel or func snuck in via the parsed existing data), but the error is wrapped defensively.","triggerScenarios":"json.Marshal fails on the merged metadata map — practically only when existing parsed metadata contained values of unsupported types that survive into the output map.","commonSituations":"Extremely rare; typically indicates corrupted or programmatically injected metadata with non-JSON-encodable values. Most users will never see this.","solutions":["Inspect the issue's metadata for unsupported/garbage values and reset it to a plain JSON object","Retry the sync; if persistent, report the metadata content that triggers it as a bug","Update bd to the latest version in case the merge logic changed"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if _, err := json.Marshal(data); err != nil {\n\t// abort before calling the sync API\n}","typeGuard":null,"tryCatchPattern":"raw, err := mergedLinearMilestoneMetadata(existing, ms)\nif err != nil {\n\treturn fmt.Errorf(\"merge milestone metadata failed: %w\", err)\n}","preventionTips":["Keep metadata values to JSON-encodable primitives and maps","Avoid injecting Go values with channels/funcs into metadata maps","Report persistent marshal failures with the offending metadata to maintainers"],"tags":["json","metadata","linear","serialization"],"backgroundTag":"json-marshal-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}