twentyhq/twenty · error · Error

Directory ${appDirectory} already exists and is not empty

Error message

Directory ${appDirectory} already exists and is not empty

What it means

Thrown by the create-twenty-app scaffolder's validateDirectory guard before writing any files. It refuses to generate a project into a directory that already exists and contains at least one entry, to prevent silently overwriting or interleaving with existing content. An empty existing directory is allowed; any non-empty one is not.

Source

Thrown at packages/create-twenty-app/src/create-app.command.ts:227

      options.displayName?.trim() || convertToLabel(appName);

    const appDescription = (options.description ?? '').trim();

    const appDirectory = options.directory
      ? path.join(CURRENT_EXECUTION_DIRECTORY, options.directory)
      : path.join(CURRENT_EXECUTION_DIRECTORY, kebabCase(appName));

    return { appName, appDisplayName, appDirectory, appDescription };
  }

  private async validateDirectory(appDirectory: string): Promise<void> {
    if (!(await fs.pathExists(appDirectory))) {
      return;
    }

    const files = await fs.readdir(appDirectory);
    if (files.length > 0) {
      throw new Error(
        `Directory ${appDirectory} already exists and is not empty`,
      );
    }
  }

  private logPlan({
    appName,
    appDisplayName,
    appDescription,
    appDirectory,
  }: {
    appName: string;
    appDisplayName: string;
    appDescription: string;
    appDirectory: string;
  }): void {
    console.log(chalk.blue('\nCreating Twenty Application\n'));
    console.log(chalk.white(`  Name:           ${appName}`));

View on GitHub (pinned to 1f5dd2bbd2)

Solutions

  1. Pick a different app name (or pass --directory ./new-folder) so the resolved path is empty or absent.
  2. Move or delete the existing directory contents: rm -rf <appDirectory> then re-run.
  3. If you intend to regenerate into the same folder, empty it first but confirm nothing valuable remains.
  4. Check for hidden files (ls -la <appDirectory>) — even one hidden entry trips the guard.

Example fix

// before
$ npx create-twenty-app   # fails: ./my-twenty-app already has files

// after — point at a fresh directory
$ npx create-twenty-app --directory my-twenty-app-2
Defensive patterns

Strategy: validation

Validate before calling

import fs from 'fs-extra';
import path from 'path';

async function assertDirectoryEmpty(target: string): Promise<void> {
  if (!(await fs.pathExists(target))) return;
  const files = await fs.readdir(target);
  if (files.length > 0) {
    throw new Error(`Refusing to scaffold: '${target}' is not empty (${files.length} entries).`);
  }
}

// run before invoking the scaffolder
await assertDirectoryEmpty(path.resolve(process.cwd(), 'my-twenty-app'));

Prevention

When it happens

Trigger: Running `npx create-twenty-app` (or the package's bin) when the resolved target directory — either the explicit --directory option or path.join(cwd, kebabCase(appName)) — already holds files. fs.pathExists returns true and fs.readdir yields a non-empty array.

Common situations: Re-running the scaffolder after a failed/partial earlier attempt left files behind; choosing a default name like my-twenty-app in a folder where another scaffold already landed; pointing --directory at an existing project root; IDE created a .DS_Store or .git keeping the dir non-empty.

Related errors


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