{"record":{"id":"0384353a5b47d1d6","repo":"phacility/phabricator","slug":"err-no-certificate","errorCode":"ERR-NO-CERTIFICATE","errorMessage":"ERR-NO-CERTIFICATE","messagePattern":"ERR-NO-CERTIFICATE","errorType":"error_code","errorClass":"ConduitException","httpStatus":null,"severity":"error","filePath":"src/applications/conduit/method/ConduitConnectConduitAPIMethod.php","lineNumber":145,"sourceCode":"              'correctly.',\n              phutil_format_relative_time($threshold),\n              $token,\n              date('r', $token),\n              $now,\n              date('r', $now),\n              ($token - $now),\n              $threshold));\n      }\n      $valid = sha1($token.$user->getConduitCertificate());\n      if (!phutil_hashes_are_identical($valid, $signature)) {\n        throw new ConduitException('ERR-INVALID-CERTIFICATE');\n      }\n      $session_key = id(new PhabricatorAuthSessionEngine())->establishSession(\n        PhabricatorAuthSession::TYPE_CONDUIT,\n        $user->getPHID(),\n        $partial = false);\n    } else {\n      throw new ConduitException('ERR-NO-CERTIFICATE');\n    }\n\n    return array(\n      'connectionID'  => mt_rand(),\n      'sessionKey'    => $session_key,\n      'userPHID'      => $user->getPHID(),\n    );\n  }\n\n}\n","sourceCodeStart":127,"sourceCodeEnd":156,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/conduit/method/ConduitConnectConduitAPIMethod.php#L127-L156","documentation":"conduit.connect only proceeds with the certificate path when BOTH authToken and authSignature are present. If either value is missing the else branch throws 'ERR-NO-CERTIFICATE' before any verification happens, i.e. the client never supplied the credentials to attempt the handshake.","triggerScenarios":"Calling conduit.connect with only the 'user' parameter; a client that skips the conduit.getcertificate step and sends no token/signature; a parameter typo like 'authtoken' that Phabricator does not recognize.","commonSituations":"Hand-written clients testing the endpoint before implementing the full handshake; parameters dropped by form-encoding bugs (nested JSON not encoded as required).","solutions":["Perform the full old-style handshake: generate a token, call conduit.getcertificate, then send both authToken (unix timestamp) and authSignature (sha1(token . certificate)) with conduit.connect.","Check the parameter names are exactly authToken and authSignature, and that both survive your encoding.","Better: abandon the legacy path and authenticate with an API token via arc install-certificate."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Client-side precondition before conduit.connect.\nif (!strlen($token) || !strlen($signature)) {\n  throw new Exception('authToken and authSignature are both required.');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Implement the full handshake sequence (token -> getcertificate -> connect) as one unit; never call connect bare.","Migrate to API-token auth, which removes this entire class of errors."],"tags":["conduit","auth","certificate","phabricator","php","legacy"],"backgroundTag":"conduit-auth-failed","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}