composer/composer · warning · RuntimeException
Could not view diff\n\n:".$output
Error message
Could not view diff\n\n:".$output
What it means
Thrown in viewDiff (src/Composer/Downloader/GitDownloader.php:588) when 'git diff HEAD' exits non-zero. viewDiff is only reached through the interactive cleanChanges prompt option 'd' (view local modifications); it is informational and the failure prevents showing the diff.
Source
Thrown at src/Composer/Downloader/GitDownloader.php:589
{
$path = $this->normalizePath($path);
if (0 !== $this->process->execute(['git', 'stash', '--include-untracked'], $output, $path)) {
throw new \RuntimeException("Could not stash changes\n\n:".$output);
}
$this->hasStashedChanges[$path] = true;
return \React\Promise\resolve(null);
}
/**
* @throws \RuntimeException
*/
protected function viewDiff(string $path): void
{
$path = $this->normalizePath($path);
if (0 !== $this->process->execute(['git', 'diff', 'HEAD'], $output, $path)) {
throw new \RuntimeException("Could not view diff\n\n:".$output);
}
$this->io->writeError($output);
}
protected function normalizePath(string $path): string
{
if (Platform::isWindows() && strlen($path) > 0) {
$basePath = $path;
$removed = [];
while (!is_dir($basePath) && $basePath !== '\\') {
array_unshift($removed, basename($basePath));
$basePath = dirname($basePath);
}
if ($basePath === '\\') {
return $path;View on GitHub (pinned to c435d285c9)
Solutions
- Run 'git -C <path> diff HEAD' manually to see the underlying error.
- If there is no HEAD yet, complete the initial checkout first.
- Repair the index ('git fsck', remove index.lock) and retry.
- Choose a different prompt option (e.g. 'v' for the file list) if diff is unavailable.
Example fix
# before: 'Could not view diff' when pressing 'd' # after git -C vendor/vendor/pkg diff HEAD # diagnose git -C vendor/vendor/pkg fsck --full composer update vendor/pkg # retry, press 'v' for file list
Defensive patterns
Strategy: try-catch
Validate before calling
// Only meaningful interactively; ensure HEAD exists before offering 'd'.
exec('git -C ' . escapeshellarg($path) . ' rev-parse --verify HEAD', $out, $rc);
if ($rc !== 0) {
// skip offering the diff option
} Try / catch
try {
$downloader->viewDiff($path);
} catch (\RuntimeException $e) {
if (str_contains($e->getMessage(), 'Could not view diff')) {
// diff is informational; degrade gracefully
return;
}
throw $e;
} Prevention
- Treat viewDiff as optional diagnostics.
- Ensure a HEAD exists (complete the initial checkout) before diffing.
- Use the file-list option ('v') if a full diff is unavailable.
When it happens
Trigger: User selects 'd' at the cleanChanges prompt; viewDiff($path) runs and $this->process->execute(['git','diff','HEAD'],$output,$path) returns non-zero at line 588.
Common situations: A repo with no HEAD yet (fresh clone before checkout); a corrupted index; git binary issues; detached state where HEAD is unreadable.
Related errors
- Update aborted
- Please answer yes, y, no, or n.
- The package name ${value} is invalid, it should be lowercase
- Invalid minimum stability "${value}". Must be empty or one o
- The src folder name "%s" is invalid. Please add a relative p
AI-assisted analysis of composer/composer@c435d285c9 (2026-08-07).
Data as JSON: /api/errors/9d651e544126af8e.
Report an issue: GitHub.