{"record":{"id":"c5f03d76e7062c30","repo":"phacility/phabricator","slug":"this-repository-is-read-only-over-ssh-tried-to-ex","errorCode":null,"errorMessage":"This repository is read-only over SSH (tried to execute protocol command \"%s\").","messagePattern":"This repository is read-only over SSH \\(tried to execute protocol command \"(.+?)\"\\)\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/diffusion/ssh/DiffusionSSHWorkflow.php","lineNumber":288,"sourceCode":"    }\n\n    if ($repository->isReadOnly()) {\n      throw new Exception($repository->getReadOnlyMessageForDisplay());\n    }\n\n    $protocol = PhabricatorRepositoryURI::BUILTIN_PROTOCOL_SSH;\n    if ($repository->canServeProtocol($protocol, true)) {\n      $can_push = PhabricatorPolicyFilter::hasCapability(\n        $viewer,\n        $repository,\n        DiffusionPushCapability::CAPABILITY);\n      if (!$can_push) {\n        throw new Exception(\n          pht('You do not have permission to push to this repository.'));\n      }\n    } else {\n      if ($protocol_command !== null) {\n        throw new Exception(\n          pht(\n            'This repository is read-only over SSH (tried to execute '.\n            'protocol command \"%s\").',\n            $protocol_command));\n      } else {\n        throw new Exception(\n          pht('This repository is read-only over SSH.'));\n      }\n    }\n\n    $this->hasWriteAccess = true;\n    return $this->hasWriteAccess;\n  }\n\n  protected function shouldSkipReadSynchronization() {\n    $viewer = $this->getSSHUser();\n\n    // Currently, the only case where devices interact over SSH without","sourceCodeStart":270,"sourceCodeEnd":306,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/diffusion/ssh/DiffusionSSHWorkflow.php#L270-L306","documentation":"requireWriteAccess() asks canServeProtocol(BUILTIN_PROTOCOL_SSH, true) whether any repository URI serves writes over SSH. When that returns false but the SSH request carried a recognized write protocol command (e.g. git-receive-pack), this exception names the offending command. The repository's SSH serving configuration is read-only - it is not a user-permission problem.","triggerScenarios":"git push over SSH while the repository's builtin SSH URI has 'Serve Over SSH' set to 'Read Only' or 'Off'; mercurial push over ssh:// against a repository whose SSH URI only serves reads.","commonSituations":"New repositories created with SSH write serving disabled; admins disabling SSH pushes in favor of HTTP; URI table edited during hosting changes and write serving never restored.","solutions":["Repository -> Manage URIs: edit the builtin SSH URI and set 'Serve Over SSH' to 'Read/Write', then retry","If SSH writes are intentionally disabled, push over the protocol that does serve writes (usually HTTP)","Check which URI clients actually use - a custom ssh:// URI may be marked observe-only while another is the intended push target"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if (!$repository->canServeProtocol(\n      PhabricatorRepositoryURI::BUILTIN_PROTOCOL_SSH,\n      true)) {\n  // refuse the write before launching the client session\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Verify canServeProtocol() for write before advertising SSH push URIs to users","After any URI migration, re-check that SSH serving is Read/Write"],"tags":["phabricator","diffusion","ssh","git-push","uri-configuration","read-only"],"backgroundTag":"repository-read-only","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}