{"record":{"id":"8e2722c9fccb263c","repo":"twentyhq/twenty","slug":"createperson-did-not-return-an-id-8e2722","errorCode":null,"errorMessage":"createPerson did not return an id","messagePattern":"createPerson did not return an id","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/twenty-apps/internal/twenty-partners/src/modules/shared/services/find-or-create-company-and-person.service.ts","lineNumber":64,"sourceCode":"  firstName: string;\n  lastName: string;\n  companyId: string;\n};\n\nexport async function findOrCreatePersonByEmail(\n  client: CoreApiClient,\n  input: FindOrCreatePersonByEmailInput,\n): Promise<string> {\n  const email = input.email.trim();\n  const firstName = input.firstName.trim();\n  const lastName = input.lastName.trim();\n\n  const existing = await findPersonIdByPrimaryEmail(client, email);\n  if (existing !== undefined) return existing;\n\n  const result = await createPerson(client, { email, firstName, lastName, companyId: input.companyId });\n  const id = result.createPerson?.id;\n  if (id === undefined) throw new Error('createPerson did not return an id');\n  return id;\n}\n","sourceCodeStart":46,"sourceCodeEnd":67,"githubUrl":"https://github.com/twentyhq/twenty/blob/1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6/packages/twenty-apps/internal/twenty-partners/src/modules/shared/services/find-or-create-company-and-person.service.ts#L46-L67","documentation":"findOrCreatePersonByEmail in the shared service guards createPerson result. After an email dedup lookup it creates a Person and asserts createPerson.id. An undefined id means the server returned a null/id-less person payload rather than throwing.","triggerScenarios":"createPerson returns { createPerson: null } or no id. Causes: caller lacks Person create permission; email/firstName/lastName invalid or empty; Person metadata out of sync; companyId relation invalid; concurrent create beating the dedup lookup.","commonSituations":"Call site passing an empty email or name; role lacks Person create; manifest changed Person fields; race creating the same contact twice.","solutions":["Inspect the raw createPerson response for null payload or errors array.","Validate email/firstName/lastName are non-empty (and email well-formed) before calling findOrCreatePersonByEmail.","Confirm input.companyId is a valid existing Company id.","Verify the caller's role has Person create permission and Person is synced."],"exampleFix":"// before\nconst result = await createPerson(client, { email, firstName, lastName, companyId: input.companyId });\nconst id = result.createPerson?.id;\nif (id === undefined) throw new Error('createPerson did not return an id');\n\n// after — guard inputs and surface result\nif (!email || !firstName || !lastName) throw new Error('email/firstName/lastName required');\nconst result = await createPerson(client, { email, firstName, lastName, companyId: input.companyId });\nconst id = result.createPerson?.id;\nif (id === undefined) {\n  throw new Error(`createPerson did not return an id (email=${email}, result=${JSON.stringify(result)})`);\n}","handlingStrategy":"type-guard","validationCode":"import { isNonEmptyString } from 'twenty-shared';\n\nexport async function findOrCreatePersonByEmailSafe(client: CoreApiClient, input: FindOrCreatePersonByEmailInput) {\n  if (!isNonEmptyString(input.email) || !isNonEmptyString(input.firstName) || !isNonEmptyString(input.lastName)) {\n    throw new Error('email, firstName, lastName are required');\n  }\n  if (!input.companyId) throw new Error('companyId is required');\n  return findOrCreatePersonByEmail(client, input);\n}","typeGuard":"const hasCreatedPersonId = (r: unknown): r is { createPerson: { id: string } } =>\n  typeof r === 'object' && r !== null &&\n  typeof (r as any).createPerson?.id === 'string';\n\nif (!hasCreatedPersonId(result)) {\n  throw new Error(`createPerson returned no id: ${JSON.stringify(result)}`);\n}","tryCatchPattern":null,"preventionTips":["Validate email/firstName/lastName non-empty and email well-formed before createPerson.","Confirm companyId is a valid existing Company id.","Always select and assert id on createPerson results.","Confirm Person create permission and metadata sync."],"tags":["graphql","sdk","mutation","partners","shared"],"backgroundTag":null,"analyzedSha":"1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6","analyzedAt":"2026-08-12T15:37:27.593Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}