{"record":{"id":"b66acc30f4923367","repo":"phacility/phabricator","slug":"two-servers-at-indexes-s-and-s-both-bind-t","errorCode":null,"errorMessage":"Two servers (at indexes \"%s\" and \"%s\") both bind to the same port (\"%s\"). Each server must bind to a unique port.","messagePattern":"Two servers \\(at indexes \"(.+?)\" and \"(.+?)\"\\) both bind to the same port \\(\"(.+?)\"\\)\\. Each server must bind to a unique port\\.","errorType":"console","errorClass":"PhutilArgumentUsageException","httpStatus":null,"severity":"error","filePath":"src/applications/aphlict/management/PhabricatorAphlictManagementWorkflow.php","lineNumber":111,"sourceCode":"    $has_admin = false;\n    $port_map = array();\n    foreach ($servers as $index => $server) {\n      PhutilTypeSpec::checkMap(\n        $server,\n        array(\n          'type' => 'string',\n          'port' => 'int',\n          'listen' => 'optional string|null',\n          'ssl.key' => 'optional string|null',\n          'ssl.cert' => 'optional string|null',\n          'ssl.chain' => 'optional string|null',\n        ));\n\n      $port = $server['port'];\n      if (!isset($port_map[$port])) {\n        $port_map[$port] = $index;\n      } else {\n        throw new PhutilArgumentUsageException(\n          pht(\n            'Two servers (at indexes \"%s\" and \"%s\") both bind to the same '.\n            'port (\"%s\"). Each server must bind to a unique port.',\n            $port_map[$port],\n            $index,\n            $port));\n      }\n\n      $type = $server['type'];\n      switch ($type) {\n        case 'admin':\n          $has_admin = true;\n          break;\n        case 'client':\n          $has_client = true;\n          break;\n        default:\n          throw new PhutilArgumentUsageException(","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/aphlict/management/PhabricatorAphlictManagementWorkflow.php#L93-L129","documentation":"Thrown while validating the 'servers' list in the Aphlict config when two server entries declare the same 'port' value. The workflow builds a $port_map keyed by port and rejects duplicates regardless of server type, because the Node.js notification server cannot bind two listeners to one port.","triggerScenarios":"Two entries in the \"servers\" array share a \"port\" value — e.g. an admin server on 22281 and a client server also set to 22281 (copy-paste from the example config where only one port was changed).","commonSituations":"Cloning the stock example config (client 22280 / admin 22281) and editing only one field; merging two team configs that each chose the same port; changing a port to dodge a conflict but forgetting a second entry.","solutions":["Open the config and give each server entry in \"servers\" a distinct \"port\" (convention: client 22280, admin 22281)","Check no other service already uses the new port: ss -ltnp | grep <port>","If you actually want one port for both roles, note Aphlict does not support that — keep separate admin and client listeners"],"exampleFix":"// before\n\"servers\": [\n  {\"type\": \"client\", \"port\": 22280, \"listen\": \"0.0.0.0\"},\n  {\"type\": \"admin\",  \"port\": 22280}\n]\n// after\n\"servers\": [\n  {\"type\": \"client\", \"port\": 22280, \"listen\": \"0.0.0.0\"},\n  {\"type\": \"admin\",  \"port\": 22281, \"listen\": \"127.0.0.1\"}\n]","handlingStrategy":"validation","validationCode":"$ports = array();\nforeach ($config['servers'] as $i => $server) {\n  $port = $server['port'];\n  if (isset($ports[$port])) {\n    throw new InvalidArgumentException(\"Duplicate port {$port} at indexes {$ports[$port]} and {$i}\");\n  }\n  $ports[$port] = $i;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use distinct well-known ports per role (client 22280, admin 22281) as a convention","When cloning example configs, grep for reused port numbers before deploying"],"tags":["aphlict","port-conflict","configuration","phabricator"],"backgroundTag":"duplicate-port-binding","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}