phacility/phabricator · error · Exception
Expected `%s`!
Error message
Expected `%s`!
What it means
executeRepositoryOperations() requires the SSH command to be 'svnserve' with the tunnel flag: the workflow registers a single 'tunnel/-t' argument and throws 'Expected svnserve -t!' when it is absent. That argument is exactly how the standard svn+ssh transport invokes the server, so anything else indicates a hand-rolled tunnel command.
Source
Thrown at src/applications/diffusion/ssh/DiffusionSubversionServeSSHWorkflow.php:147
'Client closed connection before sending a complete protocol '.
'frame.'));
}
// If the client has disconnected, kill the subprocess and bail.
if (!$io_channel->isOpenForWriting()) {
throw new Exception(
pht(
'Client closed connection before receiving response.'));
}
}
}
protected function executeRepositoryOperations() {
$repository = $this->getRepository();
$args = $this->getArgs();
if (!$args->getArg('tunnel')) {
throw new Exception(pht('Expected `%s`!', 'svnserve -t'));
}
if ($this->shouldProxy()) {
// NOTE: We're always requesting a writable device here. The request
// might be read-only, but we can't currently tell, and SVN requests
// can mix reads and writes.
$command = $this->getProxyCommand(true);
$this->isProxying = true;
$cwd = null;
} else {
$command = csprintf(
'svnserve -t --tunnel-user=%s',
$this->getSSHUser()->getUsername());
$cwd = PhabricatorEnv::getEmptyCWD();
}
$command = PhabricatorDaemon::sudoCommandAsDaemonUser($command);
$future = new ExecFuture('%C', $command);View on GitHub (pinned to 5720a38cfe)
Solutions
- Use plain svn+ssh://user@host/REPO URLs so the client sends exactly 'svnserve -t'
- Edit the [tunnels] section of ~/.subversion/config and strip extra arguments from the tunnel definition
- Smoke-test with 'ssh user@host svnserve -t' (should connect silently) before retrying svn
Example fix
# before: custom tunnel with extra args # ~/.subversion/config: ssh = ssh -p 2222 phab@host svnserve -r /var/repos svn checkout svn+ssh://phab@host/var/repos/REPO # after: standard builtin tunnel, no rewriting # (remove the custom 'ssh' tunnel entry or keep only port flags) svn checkout svn+ssh://phab@host/REPO
Defensive patterns
Strategy: validation
Validate before calling
# The SVN tunnel command must be exactly 'svnserve -t' (no -r, no paths). # Verify before connecting: $ ssh phab@host svnserve -t # connects silently -> tunnel shape is correct
Prevention
- Prefer the repository's documented builtin svn+ssh URI over hand-built tunnels
- Smoke-test 'ssh user@host svnserve -t' after any tunnel configuration change
When it happens
Trigger: Manual 'ssh phabricator@host svnserve' without -t; a custom tunnel in the [tunnels] section of ~/.subversion/config that replaces or adds arguments (e.g. -r /var/repos); wrappers around the svn ssh tunnel that drop -t.
Common situations: Developers hand-building tunnels to add ports or users; recipes carried over from plain-svnserve servers that rooted the repo with -r; documentation copy-paste of old svn+ssh snippets.
Related errors
- This repository is read-only over SSH.
- %s subprocess exited before emitting a protocol frame.
- Client closed connection before sending a complete protocol
- Client closed connection before receiving response.
- This public key is already associated with another user or d
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/30a607ed863fb087.
Report an issue: GitHub.