{"record":{"id":"ee6641275f4de45c","repo":"gastownhall/beads","slug":"missing-external-ref-for-linear-issue-s","errorCode":null,"errorMessage":"missing external ref for Linear issue %s","messagePattern":"missing external ref for Linear issue (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/linear.go","lineNumber":551,"sourceCode":"\t\t}\n\t\thooks.GenerateID = generateID\n\t}\n\n\tif opts.Milestones && st != nil {\n\t\thooks.AfterConvert = func(ctx context.Context, extIssue *tracker.TrackerIssue, conv *tracker.IssueConversion, ref string, _ *types.Issue, syncOpts tracker.SyncOptions) error {\n\t\t\tli, ok := extIssue.Raw.(*linear.Issue)\n\t\t\tif !ok || li == nil || li.ProjectMilestone == nil {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tif syncOpts.DryRun || opts.DryRun {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tmilestoneRef, err := ensureLinearMilestoneEpic(ctx, st, li.ProjectMilestone, hookActor, generateID)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif strings.TrimSpace(ref) == \"\" {\n\t\t\t\treturn fmt.Errorf(\"missing external ref for Linear issue %s\", extIssue.Identifier)\n\t\t\t}\n\t\t\tconv.Dependencies = append(conv.Dependencies, tracker.DependencyInfo{\n\t\t\t\tFromExternalID: ref,\n\t\t\t\tToExternalID:   milestoneRef,\n\t\t\t\tType:           string(types.DepParentChild),\n\t\t\t\tSource:         tracker.DependencySourceParent,\n\t\t\t})\n\t\t\treturn nil\n\t\t}\n\t}\n\n\treturn hooks\n}\n\nconst linearMilestoneExternalRefPrefix = \"linear:project-milestone:\"\n\nfunc linearMilestoneExternalRef(id string) string {\n\treturn linearMilestoneExternalRefPrefix + strings.TrimSpace(id)","sourceCodeStart":533,"sourceCodeEnd":569,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/linear.go#L533-L569","documentation":"During Linear import/sync, when converting dependencies involving a project milestone, the code requires the milestone's epic external ref. If the resolved ref string is empty, this error aborts conversion for that issue, since a dependency cannot be recorded without a FromExternalID.","triggerScenarios":"Linear sync hits an issue whose milestone epic lookup/creation returned an empty ref string (e.g. ensureLinearMilestoneEpic returned empty without error due to unexpected data) while appending a parent-child dependency to conv.Dependencies.","commonSituations":"Linear workspace data quirks — milestone objects with empty identifiers; a partially completed import where the milestone epic was matched but ref assignment was skipped; custom sync scripts feeding unusual Linear payloads.","solutions":["Inspect the Linear issue's project milestone data for empty/blank identifiers","Re-run the sync so ensureLinearMilestoneEpic recreates the milestone epic with a valid external ref","Check for prior import failures that left the milestone epic without an external ref and repair or delete that epic record"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before appending the dependency, verify the ref\nif strings.TrimSpace(ref) == \"\" {\n    log.Printf(\"skipping dependency for %s: empty external ref\", extIssue.Identifier)\n    return nil\n}","typeGuard":"func hasExternalRef(issue *types.Issue) bool {\n    return issue.ExternalRef != nil && strings.TrimSpace(*issue.ExternalRef) != \"\"\n}","tryCatchPattern":"// the sync pipeline returns this error directly; catch at the import boundary\nif err := runLinearSync(ctx); err != nil {\n    if strings.Contains(err.Error(), \"missing external ref\") { /* log issue ID and continue/skip */ }\n    return err\n}","preventionTips":["Validate Linear milestone payloads (non-empty IDs and refs) before conversion","Repair or delete milestone epics left without external refs by failed imports","Re-run sync after fixing upstream Linear data so refs are regenerated"],"tags":["linear","sync","external-ref","import"],"backgroundTag":"missing-external-ref","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}