phacility/phabricator · error · Exception
Unexpected command structure, expected '%s'.
Error message
Unexpected command structure, expected '%s'.
What it means
Phabricator's Subversion-over-SSH protocol handler parses each client command into a nested ( ... ) structure. isReadOnlyCommand() requires element 0 of that structure to be a token of type 'word' (the command name, like EXTERNAL or reparent) so it can classify the command; any other shape fails defensively with an Exception instead of being guessed read-only.
Source
Thrown at src/applications/diffusion/protocol/DiffusionSubversionWireProtocol.php:167
default:
throw new Exception(
pht(
"Unknown SVN wire protocol structure '%s'!",
$type));
}
if ($type != 'list') {
$out[] = ' ';
}
}
$out[] = ') ';
return implode('', $out);
}
public function isReadOnlyCommand(array $struct) {
if (empty($struct[0]['type']) || ($struct[0]['type'] != 'word')) {
// This isn't what we expect; fail defensively.
throw new Exception(
pht(
"Unexpected command structure, expected '%s'.",
'( word ... )'));
}
switch ($struct[0]['value']) {
// Authentication command set.
case 'EXTERNAL':
// The "Main" command set. Some of the commands in this command set are
// mutation commands, and are omitted from this list.
case 'reparent':
case 'get-latest-rev':
case 'get-dated-rev':
case 'rev-proplist':
case 'rev-prop':
case 'get-file':
case 'get-dir':View on GitHub (pinned to 5720a38cfe)
Solutions
- Reproduce with a stock svn client; if stock svn works, capture the raw bytes the failing client sends
- Check for proxies or wrapper scripts corrupting ssh stdin
- If a normal svn client triggers it, file a bug upstream with the captured payload
Defensive patterns
Strategy: type-guard
Validate before calling
// validate the parsed structure before classification
if (!isset($struct[0]['type']) || $struct[0]['type'] !== 'word') {
// reject the command with a protocol error
} Type guard
function isSvnWordCommandStruct(array $struct) {
return isset($struct[0]['type']) && $struct[0]['type'] === 'word';
} Try / catch
try {
$read_only = $protocol->isReadOnlyCommand($struct);
} catch (Exception $ex) {
// reject the client request with a protocol error; keep the ssh service running
} Prevention
- Health-check the svn endpoint with a real svn client, not raw TCP probes
- Log malformed structures with their raw payload to catch middlebox corruption early
When it happens
Trigger: A client sends a command whose first parsed element is not a word: non-svn input hitting the svn endpoint, a corrupted or desynchronized protocol stream, truncated stdin over ssh, or a parser edge case.
Common situations: Scanners or health checks sending garbage bytes to the ssh service; unusual svn client dialects; middleboxes corrupting the ssh stream.
Related errors
- Unknown Mercurial command "%s"!
- Subversion does not support searching for ancestors of a par
- Unexpected number of output lines from "git diff-tree" when
- Unsupported currency '%s'!
- Failed to parse line '%s'.
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/36fc9347335dca3c.
Report an issue: GitHub.