{"record":{"id":"db30720ecd5d5ba9","repo":"phacility/phabricator","slug":"client-closed-connection-before-receiving-response","errorCode":null,"errorMessage":"Client closed connection before receiving response.","messagePattern":"Client closed connection before receiving response\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"warning","filePath":"src/applications/diffusion/ssh/DiffusionSubversionServeSSHWorkflow.php","lineNumber":135,"sourceCode":"          $uri = $struct[2]['value'];\n          $path = $this->getPathFromSubversionURI($uri);\n\n          return $this->loadRepositoryWithPath(\n            $path,\n            PhabricatorRepositoryType::REPOSITORY_TYPE_SVN);\n        }\n      }\n\n      if (!$io_channel->isOpenForReading()) {\n        throw new Exception(\n          pht(\n            'Client closed connection before sending a complete protocol '.\n            'frame.'));\n      }\n\n      // If the client has disconnected, kill the subprocess and bail.\n      if (!$io_channel->isOpenForWriting()) {\n        throw new Exception(\n          pht(\n            'Client closed connection before receiving response.'));\n      }\n    }\n  }\n\n  protected function executeRepositoryOperations() {\n    $repository = $this->getRepository();\n\n    $args = $this->getArgs();\n    if (!$args->getArg('tunnel')) {\n      throw new Exception(pht('Expected `%s`!', 'svnserve -t'));\n    }\n\n    if ($this->shouldProxy()) {\n      // NOTE: We're always requesting a writable device here. The request\n      // might be read-only, but we can't currently tell, and SVN requests\n      // can mix reads and writes.","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/diffusion/ssh/DiffusionSubversionServeSSHWorkflow.php#L117-L153","documentation":"The mirrored case: the IO channel reports the peer is no longer open for writing from the server's perspective - the client disconnected before receiving the server's response. The workflow kills the subprocess and aborts instead of writing to a dead socket.","triggerScenarios":"Client disconnects while svnserve computes or streams a response: killed checkout, closed laptop, proxy idle-timeout cutting the SSH session.","commonSituations":"Long checkouts dropped by NAT/firewall idle timers; CI cancellation mid-operation; VPN/mobile users dropping during large transfers.","solutions":["Retry the operation; if it recurs for one client only, inspect that client's network path","Raise SSH keep-alives (ServerAliveInterval on the client) so stateful middleboxes keep the session alive","For huge working copies, use sparse checkouts or chunked exports to shorten session lifetime"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  $workflow->execute($args);\n} catch (Exception $ex) {\n  // Peer went away mid-response: kill the subprocess and release the\n  // repository write lock so the next session is not blocked.\n  $future->resolveKill();\n  return 1;\n}","preventionTips":["Enable SSH keep-alives (ServerAliveInterval) on long checkout clients","Keep sessions short (chunked exports) to shrink the window for mid-response disconnects"],"tags":["phabricator","svn","ssh","disconnect","network"],"backgroundTag":"client-disconnected","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}