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

  1. Use plain svn+ssh://user@host/REPO URLs so the client sends exactly 'svnserve -t'
  2. Edit the [tunnels] section of ~/.subversion/config and strip extra arguments from the tunnel definition
  3. 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

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


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/30a607ed863fb087. Report an issue: GitHub.