composer/composer · error · RuntimeException

Failed to execute {command}\n\n{processErrorOutput}

Error message

Failed to execute {command}\n\n{processErrorOutput}

What it means

Thrown inside SvnDownloader::getCommitLogs() when `svn info --non-interactive --xml <path>` exits non-zero. This code path only runs in verbose mode (composer update -v) for packages whose source references look like `@<revision>`, to print the changelog between the old and new revision. The exception bundles the exact failed command and svn's stderr so the failure is diagnosable.

Source

Thrown at src/Composer/Downloader/SvnDownloader.php:198

                        '    ? - print help',
                    ]);
                    break;
            }
        }

        return \React\Promise\resolve(null);
    }

    /**
     * @inheritDoc
     */
    protected function getCommitLogs(string $fromReference, string $toReference, string $path): string
    {
        if (Preg::isMatch('{@(\d+)$}', $fromReference) && Preg::isMatch('{@(\d+)$}', $toReference)) {
            // retrieve the svn base url from the checkout folder
            $command = ['svn', 'info', '--non-interactive', '--xml', '--', $path];
            if (0 !== $this->process->execute($command, $output, $path)) {
                throw new \RuntimeException(
                    'Failed to execute ' . implode(' ', $command) . "\n\n" . $this->process->getErrorOutput()
                );
            }

            $urlPattern = '#<url>(.*)</url>#';
            if (Preg::isMatchStrictGroups($urlPattern, $output, $matches)) {
                $baseUrl = $matches[1];
            } else {
                throw new \RuntimeException(
                    'Unable to determine svn url for path '. $path
                );
            }

            // strip paths from references and only keep the actual revision
            $fromRevision = Preg::replace('{.*@(\d+)$}', '$1', $fromReference);
            $toRevision = Preg::replace('{.*@(\d+)$}', '$1', $toReference);

            $command = ['svn', 'log', '-r', $fromRevision.':'.$toRevision, '--incremental'];

View on GitHub (pinned to c435d285c9)

Solutions

  1. Re-run without `-v`/`--verbose` to skip the changelog-fetching code path entirely (the install/update still works).
  2. Re-establish SVN connectivity and credentials: run `svn info <repo-url>` manually in the vendor dir and authenticate.
  3. If the .svn metadata is corrupt, delete vendor/<pkg> and let composer re-checkout.
  4. Clear `svn-cache-credentials` misconfiguration in the repository config if auth is the root cause.

Example fix

# before (triggers changelog fetch that needs svn server access)
composer update vendor/pkg -vvv

# after (skips getCommitLogs path)
composer update vendor/pkg
Defensive patterns

Strategy: try-catch

Try / catch

try {
    $composer->getEventDispatcher()->dispatchScript(\Composer\Script\ScriptEvents::POST_UPDATE_CMD);
} catch (\RuntimeException $e) {
    if (str_starts_with($e->getMessage(), 'Failed to execute svn info')) {
        // changelog fetch failed in verbose mode; safe to continue if the actual checkout succeeded
        $io->writeError('<warning>SVN changelog unavailable: '.$e->getMessage().'</warning>');
    } else {
        throw $e;
    }
}

Prevention

When it happens

Trigger: `composer update -v` on an SVN-sourced package where both old and new source references end in `@<digits>`; the checkout folder exists but `svn info` fails (lost network/auth, corrupted .svn metadata, server moved). The ProcessExecutor returns a non-zero exit code at SvnDownloader.php:197.

Common situations: Offline or VPN-disconnected runs with -v; expired/revoked SVN credentials after a credentials cache clear; a vendor dir whose .svn metadata was partially deleted; SVN server migrated to a new URL.

Related errors


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