{"record":{"id":"29355331d2aaff25","repo":"hcengineering/platform","slug":"account-status-personnotfound","errorCode":"account.status.PersonNotFound","errorMessage":"PersonNotFound","messagePattern":"PersonNotFound","errorType":"error_code","errorClass":"PlatformError","httpStatus":null,"severity":"error","filePath":"server/account/src/operations.ts","lineNumber":3153,"sourceCode":"  const { primaryPerson, secondaryPerson } = params\n  if (primaryPerson == null || primaryPerson === '' || secondaryPerson == null || secondaryPerson === '') {\n    throw new PlatformError(new Status(Severity.ERROR, platform.status.BadRequest, {}))\n  }\n\n  if (primaryPerson === secondaryPerson) {\n    // Nothing to do\n    return false\n  }\n\n  // This is a predicate the merge dialog polls, so an unauthorized caller is answered\n  // rather than thrown at. mergeSpecifiedPersons below enforces the same rules.\n  if (!(await verifyMergePersonsAuthority(db, decodedToken, primaryPerson, secondaryPerson, false))) {\n    return false\n  }\n\n  const primaryPersonObj = await db.person.findOne({ uuid: primaryPerson })\n  if (primaryPersonObj == null) {\n    throw new PlatformError(new Status(Severity.ERROR, platform.status.PersonNotFound, { person: primaryPerson }))\n  }\n\n  const secondaryPersonObj = await db.person.findOne({ uuid: secondaryPerson })\n  if (secondaryPersonObj == null) {\n    throw new PlatformError(new Status(Severity.ERROR, platform.status.PersonNotFound, { person: secondaryPerson }))\n  }\n\n  // TODO: support checking if the source person is merged already\n\n  // Merge social ids. Re-wire the secondary person social ids to the primary person.\n  // Keep their ids. This way all PersonIds inside the workspaces will remain the same.\n  const verifiedSecondaryIds = await db.socialId.find({ personUuid: secondaryPerson, verifiedOn: { $ne: null } })\n\n  return verifiedSecondaryIds.length === 0\n}\n\nexport async function mergeSpecifiedPersons (\n  ctx: MeasureContext,","sourceCodeStart":3135,"sourceCodeEnd":3171,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/server/account/src/operations.ts#L3135-L3171","documentation":"Thrown when the primary person uuid passed to the persons-merge flow does not match any document in db.person. Authority verification has passed; the merge target simply does not exist. The error payload includes the missing person uuid.","triggerScenarios":"Calling the merge operation with a primaryPerson uuid that was deleted, mistyped, or belongs to another database; also hit when merge is attempted with a fabricated/stale uuid after authority checks were bypassed via verifyMergePersonsAuthority(..., false).","commonSituations":"Merging against an already-deleted account; copying uuids between environments (dev vs prod); referencing a person from a workspace dump that was never imported into the person collection.","solutions":["Verify the primary person exists (db.person.findOne({uuid})) before merging","Re-fetch the correct uuid from the source system","Point the operation at the environment where the person actually exists"],"exampleFix":"// before\nawait mergePersons(token, { primaryPerson: staleUuid, secondaryPerson: okUuid })\n// after\nconst p = await db.person.findOne({ uuid: staleUuid })\nif (!p) throw new Error(`unknown primary person ${staleUuid}`)\nawait mergePersons(token, { primaryPerson: staleUuid, secondaryPerson: okUuid })","handlingStrategy":"validation","validationCode":"const primary = await db.person.findOne({ uuid: primaryPerson })\nif (primary == null) throw new Error(`primary person ${primaryPerson} not found`)","typeGuard":"function primaryExists(p: Person | null, uuid: string): p is Person {\n  return p != null && p.uuid === uuid\n}","tryCatchPattern":"try {\n  await mergePersons(token, { primaryPerson, secondaryPerson })\n} catch (err) {\n  if ((err as PlatformError).props?.code === platform.status.PersonNotFound) {\n    console.error('primary person missing; verify uuid and environment')\n  } else throw err\n}","preventionTips":["Confirm person existence before merge workflows","Avoid copying uuids across environments","Handle deleted persons in queued merge jobs"],"tags":["person-not-found","merge","account","data"],"backgroundTag":"person-not-found","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}