twentyhq/twenty · critical · Error

defineApplication in ${configPath} must declare a universalI

Error message

defineApplication in ${configPath} must declare a universalIdentifier before generating entities.

What it means

Thrown by the Twenty SDK CLI when it found an application config file at a recognized path but the extracted config object has no universalIdentifier property. The universalIdentifier is the root seed for all deterministically generated identifiers, so its absence makes code generation impossible. This is a stricter check than error 82 — the file exists but is incomplete.

Source

Thrown at packages/twenty-sdk/src/cli/utilities/application/get-application-universal-identifier-or-throw.ts:32

export const getApplicationUniversalIdentifierOrThrow = async (
  appPath: string,
): Promise<string> => {
  const configPath = await findAppConfigPath(appPath);

  if (configPath === null) {
    throw new Error(
      `Could not find the application config file (expected one of: ${APP_CONFIG_CANDIDATE_PATHS.join(', ')}). Create it with defineApplication({ universalIdentifier: ... }) before generating entities.`,
    );
  }

  const { config } =
    await extractManifestFromFile<ApplicationConfigWithUniversalIdentifier>({
      appPath,
      filePath: configPath,
    });

  if (!config?.universalIdentifier) {
    throw new Error(
      `defineApplication in ${configPath} must declare a universalIdentifier before generating entities.`,
    );
  }

  return config.universalIdentifier;
};

View on GitHub (pinned to 1f5dd2bbd2)

Solutions

  1. Add universalIdentifier to your defineApplication call: defineApplication({ universalIdentifier: 'com.yourcompany.yourapp' }).
  2. Use a reverse-DNS format for the identifier to ensure global uniqueness (e.g. com.acme.sales-tools).
  3. Ensure the value is a non-empty string — empty strings are falsy and will fail the !config?.universalIdentifier check.
  4. Verify the defineApplication call is exported as default from the config file so the manifest extractor can read it.

Example fix

// before — src/application.config.ts
import { defineApplication } from 'twenty-sdk';
export default defineApplication({ name: 'MyApp' });

// after
import { defineApplication } from 'twenty-sdk';
export default defineApplication({
  universalIdentifier: 'com.acme.sales-tools',
  name: 'MyApp',
});
Defensive patterns

Strategy: validation

Validate before calling

import { extractManifestFromFile } from '@/cli/utilities/build/manifest/manifest-extract-config-from-file';

const config = (await extractManifestFromFile({
  appPath,
  filePath: configPath,
})).config;

if (!config?.universalIdentifier) {
  throw new Error('Add universalIdentifier to your defineApplication call.');
}

Type guard

const hasUniversalIdentifier = (
  config: unknown,
): config is { universalIdentifier: string } => {
  return (
    typeof config === 'object' &&
    config !== null &&
    'universalIdentifier' in config &&
    typeof (config as { universalIdentifier: unknown }).universalIdentifier === 'string' &&
    (config as { universalIdentifier: string }).universalIdentifier.length > 0
  );
};

Try / catch

try {
  const id = await getApplicationUniversalIdentifierOrThrow(appPath);
} catch (error) {
  if (error instanceof Error && error.message.includes('must declare a universalIdentifier')) {
    console.error('Add universalIdentifier to src/application.config.ts');
    process.exit(1);
  }
  throw error;
}

Prevention

When it happens

Trigger: The config file is found but defineApplication was called without a universalIdentifier argument, or the config object extracted from the manifest is empty/undefined. This can also happen if extractManifestFromFile cannot statically analyze the defineApplication call's arguments.

Common situations: Developer created the config file with defineApplication({ name: 'MyApp' }) but forgot universalIdentifier. Or they used defineApplication() with no arguments. The file was created from an outdated template that didn't include the field.

Related errors


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