{"record":{"id":"1fd69f1fe4a1e33a","repo":"usememos/memos","slug":"parent-memo-not-found","errorCode":null,"errorMessage":"parent memo not found","messagePattern":"parent memo not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/router/api/v1/memo_update_helpers.go","lineNumber":51,"sourceCode":"\t\treturn nil, nil, nil, errors.Wrap(err, \"failed to list attachments\")\n\t}\n\trelations, err := s.loadMemoRelations(ctx, memo)\n\tif err != nil {\n\t\treturn nil, nil, nil, errors.Wrap(err, \"failed to load memo relations\")\n\t}\n\tmemoMessage, err := s.convertMemoFromStore(ctx, memo, reactions, attachments, relations)\n\tif err != nil {\n\t\treturn nil, nil, nil, errors.Wrap(err, \"failed to convert memo\")\n\t}\n\n\tvar parentMemo *store.Memo\n\tif memo.ParentUID != nil {\n\t\tparentMemo, err = s.Store.GetMemo(ctx, &store.FindMemo{UID: memo.ParentUID})\n\t\tif err != nil {\n\t\t\treturn nil, nil, nil, errors.Wrap(err, \"failed to get parent memo\")\n\t\t}\n\t\tif parentMemo == nil {\n\t\t\treturn nil, nil, nil, errors.New(\"parent memo not found\")\n\t\t}\n\t\tmemoMessage.Visibility = convertVisibilityFromStore(parentMemo.Visibility)\n\t}\n\n\treturn memo, parentMemo, memoMessage, nil\n}\n\nfunc (s *APIV1Service) dispatchMemoUpdatedSideEffects(ctx context.Context, memo *store.Memo, parentMemo *store.Memo, memoMessage *v1pb.Memo) {\n\tif err := s.DispatchMemoUpdatedWebhook(ctx, memoMessage); err != nil {\n\t\tslog.Warn(\"Failed to dispatch memo updated webhook\", slog.Any(\"err\", err))\n\t}\n\n\tvisibility := memo.Visibility\n\tif parentMemo != nil {\n\t\tvisibility = parentMemo.Visibility\n\t}\n\ts.SSEHub.Broadcast(&SSEEvent{\n\t\tType:       SSEEventMemoUpdated,","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/usememos/memos/blob/14d757ce1fb31c78590f374bc042f8dbedbc20d7/server/router/api/v1/memo_update_helpers.go#L33-L69","documentation":"During a memo update, if the stored memo references a ParentUID, the helper re-fetches the parent by UID to inherit its visibility. A nil parent (UID set but no matching row) aborts with this error instead of silently keeping an orphaned reply thread. It is a data-integrity check on the parent reference.","triggerScenarios":"Updating a memo whose parent_id/ParentUID points to a deleted memo; parent deleted in another session while the child edit is in flight; database restored or partially migrated leaving dangling parent references.","commonSituations":"Deleting a parent memo without cascade-detaching children; multi-tab editing races; imports that preserved parent UIDs from a different instance.","solutions":["Re-fetch the parent (GetMemo with the ParentUID) and if missing, clear the child's parent field (set parent to empty/unset) before updating.","When implementing memo deletion, detach children (clear their parent) in the same flow.","Repair dangling references directly in the database or via a script if the corruption already exists."],"exampleFix":"// before\nawait memoClient.updateMemo({ memo: { name, content, ...staleMemo } }); // stale parent set\n\n// after\nlet parent;\ntry { parent = await memoClient.getMemo({ name: parentName }); } catch { parent = null; }\nconst memo = parent ? { ...staleMemo } : { ...staleMemo, parent: undefined };","handlingStrategy":"validation","validationCode":"if (memo.parent) {\n  const parent = await memoClient.getMemo({ name: memo.parent }).catch(() => null);\n  if (!parent) memo = { ...memo, parent: undefined }; // detach orphaned reference before update\n}","typeGuard":null,"tryCatchPattern":"try { await memoClient.updateMemo({ memo }); }\ncatch (e) {\n  if (e.message.includes('parent memo not found')) {\n    await memoClient.updateMemo({ memo: { ...memo, parent: undefined } });\n    return;\n  }\n  throw e;\n}","preventionTips":["When deleting a memo, clear parent references on its children in the same operation/flow.","Treat parent references as owned data: validate them on read in the UI.","After DB restores or imports, run a consistency check for dangling parent UIDs."],"tags":["memo","parent-child","not-found","data-integrity"],"backgroundTag":null,"analyzedSha":"14d757ce1fb31c78590f374bc042f8dbedbc20d7","analyzedAt":"2026-08-15T09:27:36.538Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}