phacility/phabricator · error · Exception
Unexpected end of file.
Error message
Unexpected end of file.
What it means
The SVN recursive-listing parser reached end of file without ever seeing the closing `</list>` element that sets $done = true. This means the `svn ls -R --xml` output (or its cached copy in /tmp/diffusion.*.svnls) was truncated, empty, or never entered a valid entry loop - the state machine ran out of input while still expecting more XML.
Source
Thrown at src/applications/repository/worker/commitchangeparser/PhabricatorRepositorySvnCommitChangeParserWorker.php:762
$expect,
$line));
}
$mode = 'list2';
break;
case 'list2':
if (!preg_match('/^\s+path="/', $line)) {
throw new Exception(
pht(
"Expected '%s', got %s.",
' path=...',
$line));
}
$mode = 'entry-or-end';
break;
}
}
if (!$done) {
throw new Exception(pht('Unexpected end of file.'));
}
return $map;
}
// TODO: Replace with DiffusionPathIDQuery::getParentPath().
private function getParentPath($path) {
$path = rtrim($path, '/');
$path = dirname($path);
if (!$path) {
$path = '/';
}
return $path;
}
// TODO: Replace with DiffusionPathIDQuery::expandPathToRoot().
private function expandAllParentPaths($path, $include_self = false) {
$parents = array();View on GitHub (pinned to 5720a38cfe)
Solutions
- Inspect the cache file named in the exception context: `ls -la /tmp/diffusion.*.svnls` and `tail -5` it - if it is empty or lacks `</list>`, delete it and re-run.
- Check free space in sys_get_temp_dir() and raise phd memory limits (phd.memory-limit config or systemd limits) for huge repositories.
- Re-run `svn ls -R --xml <uri>@<rev> | tail -1` manually to confirm svn itself completes and ends with `</list>`; if it does not, fix svn-side issues (network, auth, timeouts).
- If output is complete but the parser bails early on a mismatch, fix the earlier 'Expected ...' error instead - the EOF is only a downstream symptom.
Example fix
// before: an empty capture is cached and only fails later at EOF
if (!Filesystem::pathExists($cache_loc)) {
$tmp = new TempFile();
$repository->execxRemoteCommand('--xml ls -R %s > %s', $path_uri, $tmp);
execx('mv %s %s', $tmp, $cache_loc);
}
// after: refuse to cache an output that never closed the list
if (!Filesystem::pathExists($cache_loc)) {
$tmp = new TempFile();
$repository->execxRemoteCommand('--xml ls -R %s > %s', $path_uri, $tmp);
if (strpos(Filesystem::readTail($tmp, 64), '</list>') === false) {
throw new Exception(pht('svn ls -R output is truncated.'));
}
execx('mv %s %s', $tmp, $cache_loc);
} Defensive patterns
Strategy: validation
Validate before calling
// Reject/truncate-cache before parsing: require the closing tag
$tail = execx('tail -c 64 %s', $cache_loc);
if (strpos($tail[0], '</list>') === false) {
Filesystem::remove($cache_loc);
throw new Exception('Refusing truncated svn listing cache.');
} Try / catch
try {
$map = $this->parseRecursiveListFileData($cache_loc);
} catch (Exception $ex) {
if (strpos($ex->getMessage(), 'Unexpected end of file') !== false) {
Filesystem::remove($cache_loc); // stale truncated cache
}
throw $ex;
} Prevention
- Never cache partial command output - verify the terminator before mv into the cache slot
- Disk-space alert on the tmp filesystem used by daemon workers
- Watch for OOM kills of phd daemons during giant-repo imports
When it happens
Trigger: Empty or partial capture file: the `--xml ls -R %s > %s` redirect produced zero bytes (auth prompt failed silently) or the TempFile was moved to the cache before fully flushed; daemon killed mid-write leaving a truncated cache; enormous repositories where svn was interrupted (timeout, OOM) before emitting `</list>`; XML output whose structure never matched earlier states so `$done` could not be set.
Common situations: phd task-daemon restarted or OOM-killed while parsing a giant SVN checkout (the comment in the code notes >1GB listings from Facebook-scale repos); disk full in /tmp so the redirect produced a short file; svn exiting non-zero with stderr not captured, leaving an empty stdout file that then gets cached and reused on later runs.
Related errors
- Specify either "--all" or "--caches", not both.
- Select caches to purge with "--all" or "--caches". Available
- Cache purger "%s" is not recognized. Available caches are: %
- When using "--caches", you must select at least one valid ca
- This repository is read-only over SSH.
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/41633fcdca12b77c.
Report an issue: GitHub.