{"record":{"id":"d3f2f8f51713c3cf","repo":"expo/expo","slug":"output-dir-cannot-be-the-same-as-the-project-dir","errorCode":null,"errorMessage":"--output-dir cannot be the same as the project directory.","messagePattern":"--output-dir cannot be the same as the project directory\\.","errorType":"validation","errorClass":"CommandError","httpStatus":null,"severity":"error","filePath":"packages/@expo/cli/src/export/exportAsync.ts","lineNumber":18,"sourceCode":"import chalk from 'chalk';\nimport path from 'path';\n\nimport * as Log from '../log';\nimport { waitUntilAtlasExportIsReadyAsync } from '../start/server/metro/debugging/attachAtlas';\nimport { FileNotifier } from '../utils/FileNotifier';\nimport { ensureDirectoryAsync, removeAsync } from '../utils/dir';\nimport { CommandError } from '../utils/errors';\nimport { ensureProcessExitsAfterDelay } from '../utils/exit';\nimport { exportAppAsync } from './exportApp';\nimport type { Options } from './resolveOptions';\n\nexport async function exportAsync(projectRoot: string, options: Options) {\n  // Ensure the output directory is created\n  const outputPath = path.resolve(projectRoot, options.outputDir);\n\n  if (outputPath === projectRoot) {\n    throw new CommandError('--output-dir cannot be the same as the project directory.');\n  } else if (projectRoot.startsWith(outputPath)) {\n    throw new CommandError(`--output-dir cannot be a parent directory of the project directory.`);\n  }\n  // Delete the output directory if it exists\n  await removeAsync(outputPath);\n  // Create the output directory\n  await ensureDirectoryAsync(outputPath);\n\n  // Export the app\n  await exportAppAsync(projectRoot, options);\n\n  // Stop any file watchers to prevent the CLI from hanging.\n  FileNotifier.stopAll();\n  // Wait until Atlas is ready, when enabled\n  // NOTE(cedric): this is a workaround, remove when `process.exit` is removed\n  await waitUntilAtlasExportIsReadyAsync(projectRoot);\n\n  // Final notes","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/expo/expo/blob/b09195aac27c9e4a63daaf12dcb6f00b6b2e08ee/packages/@expo/cli/src/export/exportAsync.ts#L1-L36","documentation":"Thrown by `exportAsync` when the resolved `--output-dir` equals the project root directory. Writing the export into the project root would clobber source files and create a recursive delete. A `CommandError` (no stack) prevents a destructive operation. The check uses `path.resolve(projectRoot, options.outputDir)` so relative paths are resolved before comparison.","triggerScenarios":"Running `expo export --output-dir .` or `--output-dir <absolute project root>`. Also if `outputDir` defaults to a value that, after resolution, lands on the project root.","commonSituations":"CI scripts that parameterise the output dir and pass `.` or an empty string. Confusion between the project root and the desired `dist` folder. Copy-pasting a command template without filling in the path.","solutions":["Point `--output-dir` at a distinct subfolder, e.g. `--output-dir dist`.","If scripting, validate the resolved path is not the project root before invoking the CLI.","Avoid `.` and absolute project-root paths for `--output-dir`."],"exampleFix":"// before\nexpo export --output-dir .\n\n// after\nexpo export --output-dir dist","handlingStrategy":"validation","validationCode":"import path from 'path';\nfunction assertSafeOutputDir(projectRoot: string, outputDir: string): void {\n  const out = path.resolve(projectRoot, outputDir);\n  if (out === path.resolve(projectRoot)) {\n    throw new Error('--output-dir must not equal the project root');\n  }\n  if (path.resolve(projectRoot).startsWith(out + path.sep)) {\n    throw new Error('--output-dir must not be an ancestor of the project root');\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Default `--output-dir` to a subfolder like `dist`.","Validate resolved paths in CI scripts before invoking `expo export`.","Never pass `.` or the project root absolute path as `--output-dir`."],"tags":["export","output-dir","validation","filesystem","command-error"],"backgroundTag":null,"analyzedSha":"b09195aac27c9e4a63daaf12dcb6f00b6b2e08ee","analyzedAt":"2026-08-12T15:59:58.304Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}