composer/composer · warning · UnexpectedValueException
Invalid input
Error message
Invalid input
What it means
Thrown by the input validator used while prompting for a public key during --update-keys. The first line pasted must match the PEM header '-----BEGIN PUBLIC KEY-----' exactly (after trim); anything else fails validation. It is an \UnexpectedValueException, and because it is raised inside the askAndValidate() validator the prompt simply re-asks the user rather than aborting the command.
Source
Thrown at src/Composer/Command/SelfUpdateCommand.php:344
return 0;
}
/**
* @throws \Exception
*/
protected function fetchKeys(IOInterface $io, Config $config): void
{
if (!$io->isInteractive()) {
throw new \RuntimeException('Public keys can not be fetched in non-interactive mode, please run Composer interactively');
}
$io->write('Open <info>https://composer.github.io/pubkeys.html</info> to find the latest keys');
$validator = static function ($value): string {
$value = (string) $value;
if (!Preg::isMatch('{^-----BEGIN PUBLIC KEY-----$}', trim($value))) {
throw new \UnexpectedValueException('Invalid input');
}
return trim($value)."\n";
};
$devKey = '';
while (!Preg::isMatch('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $devKey, $match)) {
$devKey = $io->askAndValidate('Enter Dev / Snapshot Public Key (including lines with -----): ', $validator);
while ($line = $io->ask('', '')) {
$devKey .= trim($line)."\n";
if (trim($line) === '-----END PUBLIC KEY-----') {
break;
}
}
}
file_put_contents($keyPath = $config->get('home').'/keys.dev.pub', $match[0]);
$io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
View on GitHub (pinned to c435d285c9)
Solutions
- Copy the full PEM block from https://composer.github.io/pubkeys.html starting at '-----BEGIN PUBLIC KEY-----' and ending at '-----END PUBLIC KEY-----'.
- Paste the BEGIN line verbatim as the first input.
- If the validator keeps rejecting, re-copy from the official pubkey page avoiding extra whitespace.
Example fix
// before (first pasted line) BEGIN PUBLIC KEY // after -----BEGIN PUBLIC KEY-----
Defensive patterns
Strategy: validation
Validate before calling
// Pre-validate the first line before pasting it into the prompt
$firstLine = trim($input);
if (!preg_match('{^-----BEGIN PUBLIC KEY-----$}', $firstLine)) {
fwrite(STDERR, "First line must be exactly '-----BEGIN PUBLIC KEY-----'.\n");
} Type guard
function isPemHeader(string $line): bool\n{\n return preg_match('{^-----BEGIN PUBLIC KEY-----$}', trim($line)) === 1;\n} Prevention
- Copy the entire PEM block from the official pubkey page.
- Paste the BEGIN header line exactly, including all five dashes on each side.
- Don't paste the fingerprint or an SSH key by mistake.
When it happens
Trigger: During `composer self-update --update-keys`, pasting a first line that is not exactly '-----BEGIN PUBLIC KEY-----' — missing dashes, extra whitespace, pasting a fingerprint instead, or a wrong-format key block (SelfUpdateCommand.php:341-345).
Common situations: Copying only part of the PEM header; pasting an SSH/PGP key by mistake; trailing spaces from a copy; pasting the key fingerprint rather than the PEM body.
Related errors
- Public keys can not be fetched in non-interactive mode, plea
- Not enough arguments (missing: "packages").
- Invalid working directory specified, {workingDir} does not e
- --abandoned must be one of {values}.
- Valid composer.json and composer.lock files are required to
AI-assisted analysis of composer/composer@c435d285c9 (2026-08-07).
Data as JSON: /api/errors/1f63a942d274e491.
Report an issue: GitHub.