twentyhq/twenty · error · PdlOperationError

OPERATION_FAILED

OPERATION_FAILED

Error message

Failed to create company: no id returned.

What it means

The PDL enrichment creates a company record via the `createCompany` mutation and expects an `id` back. If `createCompanyResult.createCompany?.id` is undefined, the mutation did not return a created company id and the flow throws a `PdlOperationError` (code `OPERATION_FAILED`). The surrounding try/catch specifically handles unique-constraint races by falling back to a `findCompanyId` lookup, so this throw is only reached for non-violation cases where the id is simply absent.

Source

Thrown at packages/twenty-apps/public/people-data-labs/src/logic-functions/utils/find-or-create-current-company.ts:52

    isNonEmptyString(companyMatchKeys.name) ||
    isNonEmptyString(companyMatchKeys.website);

  if (!canCreateNewCompany) {
    return undefined;
  }

  try {
    const createCompanyResult = (await client.mutation({
      createCompany: {
        __args: { data: buildCompanyCreateData(personData) },
        id: true,
      },
    })) as CreateCompanyResult;

    const createdCompanyId = createCompanyResult.createCompany?.id;

    if (!isDefined(createdCompanyId)) {
      throw new PdlOperationError('Failed to create company: no id returned.');
    }

    return createdCompanyId;
  } catch (createCompanyError) {
    if (!isUniqueViolationError(createCompanyError)) {
      throw createCompanyError;
    }

    const raceWinnerCompanyId = await findCompanyId({
      client,
      matchKeys: companyMatchKeys,
    });
    if (isDefined(raceWinnerCompanyId)) {
      return raceWinnerCompanyId;
    }

    throw createCompanyError;
  }

View on GitHub (pinned to 1f5dd2bbd2)

Solutions

  1. Inspect the full `createCompanyResult` (and any client `errors`) to see why `id` is absent before the throw.
  2. Validate the output of `buildCompanyCreateData(personData)` against the current company object's required fields.
  3. Confirm the acting user/role has permission to create companies in this workspace.
  4. If the root cause is a transient server issue, the existing race-fallback only covers unique violations; consider a guarded retry for empty-id results.

Example fix

// before
const createdCompanyId = createCompanyResult.createCompany?.id;
if (!isDefined(createdCompanyId)) {
  throw new PdlOperationError('Failed to create company: no id returned.');
}

// after — include the input and any server errors in the message
const createdCompanyId = createCompanyResult.createCompany?.id;
if (!isDefined(createdCompanyId)) {
  throw new PdlOperationError(
    `Failed to create company: no id returned (input=${JSON.stringify(buildCompanyCreateData(personData))}; errors=${JSON.stringify((createCompanyResult as any).errors ?? [])})`,
  );
}
Defensive patterns

Strategy: type-guard

Validate before calling

const createCompanyData = buildCompanyCreateData(personData);
// Validate required company fields before the mutation.
if (!isNonEmptyString(createCompanyData.name)) {
  throw new PdlOperationError('Cannot create company: name is missing from person data');
}

Type guard

const hasCreatedCompanyId = (
  r: unknown,
): r is { createCompany: { id: string } } =>
  typeof r === 'object' &&
  r !== null &&
  typeof (r as any).createCompany?.id === 'string';

Try / catch

try {
  const result = (await client.mutation({ createCompany: { __args: { data }, id: true } })) as CreateCompanyResult;
  if (!isDefined(result.createCompany?.id)) {
    throw new PdlOperationError('Failed to create company: no id returned.');
  }
  return result.createCompany.id;
} catch (createCompanyError) {
  if (isUniqueViolationError(createCompanyError)) {
    return findCompanyId({ client, matchKeys: companyMatchKeys });
  }
  throw createCompanyError;
}

Prevention

When it happens

Trigger: The mutation succeeds at the transport level but returns no `id` (server omitted the field, or returned an error shape genql maps to undefined); the company data built by `buildCompanyCreateData(personData)` is invalid in a way the server rejects without throwing; or a non-unique-violation server error is swallowed into an undefined result by the client.

Common situations: A workspace object schema change that made `createCompany` require a field the builder does not provide; a server bug returning a company without an id; permissions on the acting user that prevent company creation surfaced as a null result.

Related errors


AI-assisted analysis of twentyhq/twenty@1f5dd2bbd2 (2026-08-12). Data as JSON: /api/errors/17c25d0df26d9ede. Report an issue: GitHub.