phacility/phabricator · error · Exception
Unexpected line count from `%s`!
Error message
Unexpected line count from `%s`!
What it means
DiffusionLowLevelResolveRefsQuery handles refs that are not plain known refs (like HEAD^^^) by writing them one per line to 'git cat-file --batch-check' stdin and expecting exactly one output line per input ref. If the returned line count differs from the number of unresolved refs, the batch protocol desynchronized and this exception is raised.
Source
Thrown at src/applications/diffusion/query/lowlevel/DiffusionLowLevelResolveRefsQuery.php:141
unset($unresolved[$ref]);
}
}
// If we resolved everything, we're done.
if (!$unresolved) {
return $results;
}
// Try to resolve anything else. This stuff either doesn't exist or is
// some ref like "HEAD^^^".
$future = $repository->getLocalCommandFuture('cat-file --batch-check');
$future->write(implode("\n", $unresolved));
list($stdout) = $future->resolvex();
$lines = explode("\n", rtrim($stdout, "\n"));
if (count($lines) !== count($unresolved)) {
throw new Exception(
pht(
'Unexpected line count from `%s`!',
'git cat-file'));
}
$hits = array();
$tags = array();
$lines = array_combine($unresolved, $lines);
foreach ($lines as $ref => $line) {
$parts = explode(' ', $line);
if (count($parts) < 2) {
throw new Exception(
pht(
'Failed to parse `%s` output: %s',
'git cat-file',
$line));
}View on GitHub (pinned to 5720a38cfe)
Solutions
- Strip or reject refs containing newline characters before calling DiffusionResolveRefsQuery / DiffusionCachedResolveRefsQuery
- Reproduce manually: printf '<ref>\n' | git cat-file --batch-check inside the local clone
- Check the git binary version on repository hosts; upgrade if the batch output is malformed
- Log the $unresolved set when the exception fires to identify the offending ref string
Example fix
// before
$refs = id(new DiffusionCachedResolveRefsQuery())
->setRepository($repository)
->withRefs(array($user_supplied_ref))
->execute();
// after
if (preg_match('/[\r\n]/', $user_supplied_ref)) {
return new Aphront404Response(); // reject newline-carrying refs early
}
$refs = id(new DiffusionCachedResolveRefsQuery())
->setRepository($repository)
->withRefs(array($user_supplied_ref))
->execute(); Defensive patterns
Strategy: validation
Validate before calling
// Reject refs that would desynchronize the cat-file batch stream
foreach ($refs as $ref) {
if (strpos($ref, chr(10)) !== false || strpos($ref, chr(13)) !== false) {
throw new Exception('Invalid ref: contains a newline character');
}
} Try / catch
try {
$map = id(new DiffusionLowLevelResolveRefsQuery())
->setRepository($repository)
->withRefs($refs)
->execute();
} catch (Exception $ex) {
$map = array(); // treat every submitted ref as unresolvable and continue
} Prevention
- Never pass URL- or user-derived strings to the ref resolver without stripping newlines
- Restrict commit inputs to a known grammar (hex SHA, refs, simple suffixes) at the controller boundary
- Log the exact ref list when a batch mismatch fires so the offending string is identifiable
When it happens
Trigger: Passing ref strings containing embedded newline characters (they split one logical ref across lines or merge two refs into one), or git emitting error text instead of the batch stream. Ref strings usually arrive unvalidated from URLs or Conduit parameters.
Common situations: URLs like /diffusion/X/browse/HEAD%0Afake-ref; automation feeding raw user input as commit identifiers; unusual git versions altering batch output.
Related errors
- Failed to parse `%s` output: %s
- Unexpected object type from `%s`: %s
- Expected nonempty '%s' specification!
- Unexpected number of output lines from "git diff-tree" when
- Unexpected number of output lines from "git cat-file" when p
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/2e887409c69c9de7.
Report an issue: GitHub.