phacility/phabricator · error · Exception
Failed to parse line '%s'.
Error message
Failed to parse line '%s'.
What it means
PhabricatorRepositoryGitCommitChangeParserWorker parses git diff-tree --raw output line by line, mapping each status letter (A/D/M/T, etc.) to a DifferentialChangeType; any status or malformed line that falls through the switch throws (PhabricatorRepositoryGitCommitChangeParserWorker.php:110). Renames/copies with detection unexpectedly enabled, unknown status letters, or garbage injected into git's stdout break the parse.
Source
Thrown at src/applications/repository/worker/commitchangeparser/PhabricatorRepositoryGitCommitChangeParserWorker.php:110
$change_target = $src_path;
$move_away[$change_target][] = $change_path;
break;
case 'T':
// Type of the file changed, fall through and treat it as a
// modification. Not 100% sure this is the right thing to do but it
// seems reasonable.
case 'M':
if ($file_type == DifferentialChangeType::FILE_DIRECTORY) {
$change_type = DifferentialChangeType::TYPE_CHILD;
$is_direct = false;
} else {
$change_type = DifferentialChangeType::TYPE_CHANGE;
}
break;
// NOTE: "U" (unmerged) and "X" (unknown) statuses are also possible
// in theory but shouldn't appear here.
default:
throw new Exception(pht("Failed to parse line '%s'.", $line));
}
$changes[$change_path] = array(
'repositoryID' => $repository->getID(),
'commitID' => $commit->getID(),
'path' => $change_path,
'changeType' => $change_type,
'fileType' => $file_type,
'isDirect' => $is_direct,
'commitSequence' => $commit->getEpoch(),
'targetPath' => $change_target,
'targetCommitID' => $change_target ? $commit->getID() : null,
);
}
// Add a change to '/' since git doesn't mention it.View on GitHub (pinned to 5720a38cfe)
Solutions
- Manually run the parser's command in the repository to see the offending line: git diff-tree --no-commit-id -r --raw <sha>
- Remove any git wrappers/hooks/aliases that write to stdout, and ensure the daemon runs a clean git environment
- Update Phabricator (parser fixes for new git output land upstream) or pin git to a compatible version, then reparse the commit
Defensive patterns
Strategy: try-catch
Validate before calling
// Sanity-check git output shape before parsing (pre-flight in dev): // git diff-tree --no-commit-id -r --raw <sha> // Confirm every line's status column is one of A/D/M/T before relying on the parser.
Try / catch
try {
$changes = $parser->parseChanges($repository, $commit);
} catch (Exception $ex) {
// Preserve $line from the message to identify the raw output anomaly,
// then inspect the repo manually; do not blind-retry.
phlog($ex);
throw new PhabricatorWorkerPermanentFailureException($ex->getMessage());
} Prevention
- Run a clean, wrapper-free git environment on daemon hosts (no GIT_EXTERNAL_DIFF, aliases, or wrappers writing to stdout)
- Pin git versions on Phabricator hosts and test parser compatibility before upgrades
- Test imports of unusual commits (submodules, mode changes, merges) in a staging copy first
When it happens
Trigger: git emitting a change-status letter the switch does not handle; a git wrapper (GIT_EXTERNAL_DIFF, core.pager, aliases) or error message injecting non-diff lines into stdout; corrupted objects producing malformed raw output.
Common situations: Newer git versions changing raw diff formats; wrappers or locale settings on the daemon host; shallow/partial clones emitting warnings on stdout during diff-tree.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Unexpected number of output lines from "git diff-tree" when
- Commit "%s" is not a reachable ancestor of "%s".
- Commit "%s" is not a reachable ancestor of any ref.
- Unknown commit "%s"!
- Commit "%s" (with PHID "%s") is no longer reachable from any
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/25582438d8ee9253.
Report an issue: GitHub.