composer/composer · warning · RuntimeException

Could not remove %s

Error message

Could not remove %s

What it means

Thrown during CreateProjectCommand cleanup when Filesystem::removeDirectory() returns false for a VCS metadata directory (.git/.svn/.hg/etc.) after the user agreed (or --remove-vcs/non-interactive) to strip VCS history. The exception is actually caught immediately and printed as an error line, so it does not abort the command—it degrades the VCS-removal step.

Source

Thrown at src/Composer/Command/CreateProjectCommand.php:320

            && $installedFromVcs
            && (
                $input->getOption('remove-vcs')
                || !$io->isInteractive()
                || $io->askConfirmation('<info>Do you want to remove the existing VCS (.git, .svn..) history?</info> [<comment>y,n</comment>]? ')
            )
        ) {
            $finder = new Finder();
            $finder->depth(0)->directories()->in(Platform::getCwd())->ignoreVCS(false)->ignoreDotFiles(false);
            foreach (['.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg', '.fslckout', '_FOSSIL_'] as $vcsName) {
                $finder->name($vcsName);
            }

            try {
                $dirs = iterator_to_array($finder);
                unset($finder);
                foreach ($dirs as $dir) {
                    if (!$fs->removeDirectory((string) $dir)) {
                        throw new \RuntimeException('Could not remove '.$dir);
                    }
                }
            } catch (\Exception $e) {
                $io->writeError('<error>An error occurred while removing the VCS metadata: '.$e->getMessage().'</error>');
            }

            $hasVcs = false;
        }

        // rewriting self.version dependencies with explicit version numbers if the package's vcs metadata is gone
        if (!$hasVcs) {
            $package = $composer->getPackage();
            $configSource = new JsonConfigSource(new JsonFile('composer.json'));
            foreach (BasePackage::$supportedLinkTypes as $type => $meta) {
                foreach ($package->{'get'.$meta['method']}() as $link) {
                    if ($link->getPrettyConstraint() === 'self.version') {
                        $configSource->addLink($type, $link->getTarget(), $package->getPrettyVersion());
                    }

View on GitHub (pinned to c435d285c9)

Solutions

  1. Close editors/IDEs and any process holding the project directory, then `rm -rf <dir>/.git` manually.
  2. Check and fix directory permissions: `chmod -R u+w <project>` then retry removal.
  3. Re-run create-project; the failure is non-fatal so the project is otherwise usable.
  4. On Windows, ensure no antivirus/explorer window is locking the folder.
Defensive patterns

Strategy: fallback

Validate before calling

// Before create-project cleanup, check VCS dir writability:
$vcsDir = $projectDir . '/.git';
if (is_dir($vcsDir) && !is_writable($vcsDir)) {
    chmod($vcsDir, 0700); // attempt fix
}

Try / catch

try {
    $process = new Symfony\Component\Process\Process(['rm','-rf',$dir.'/'."$vcsName"]);
    $process->run();
} catch (\Throwable $e) {
    // non-fatal: VCS removal failed, project still usable
    error_log('VCS cleanup failed: '.$e->getMessage());
}

Prevention

When it happens

Trigger: Creating a project from a VCS source and consenting to remove VCS history, while the .git/.svn directory has restrictive permissions, is locked by another process, or sits on a filesystem where recursive removal fails.

Common situations: Windows file locks (editor/IDE holding .git files), read-only permissions, network-mounted filesystems, or antivirus locking files during deletion.

Related errors


AI-assisted analysis of composer/composer@c435d285c9 (2026-08-07). Data as JSON: /api/errors/cdaebf6f311f1de2. Report an issue: GitHub.