phacility/phabricator · error · ConduitException
ERR-INVALID-CERTIFICATE
ERR-INVALID-CERTIFICATE
Error message
ERR-INVALID-CERTIFICATE
What it means
conduit.connect verifies authSignature against sha1(authToken . user_conduit_certificate) using phutil_hashes_are_identical (a timing-safe comparison). A mismatch means the signature was not computed over the correct token+certificate pair for that user. Timestamp skew is a separate error (ERR-INVALID-TOKEN), so this is purely a wrong-secret or wrong-construction failure.
Source
Thrown at src/applications/conduit/method/ConduitConnectConduitAPIMethod.php:138
pht(
'The request you submitted is signed with a timestamp, but that '.
'timestamp is not within %s of the current time. The '.
'signed timestamp is %s (%s), and the current server time is '.
'%s (%s). This is a difference of %s seconds, but the '.
'timestamp must differ from the server time by no more than '.
'%s seconds. Your client or server clock may not be set '.
'correctly.',
phutil_format_relative_time($threshold),
$token,
date('r', $token),
$now,
date('r', $now),
($token - $now),
$threshold));
}
$valid = sha1($token.$user->getConduitCertificate());
if (!phutil_hashes_are_identical($valid, $signature)) {
throw new ConduitException('ERR-INVALID-CERTIFICATE');
}
$session_key = id(new PhabricatorAuthSessionEngine())->establishSession(
PhabricatorAuthSession::TYPE_CONDUIT,
$user->getPHID(),
$partial = false);
} else {
throw new ConduitException('ERR-NO-CERTIFICATE');
}
return array(
'connectionID' => mt_rand(),
'sessionKey' => $session_key,
'userPHID' => $user->getPHID(),
);
}
}
View on GitHub (pinned to 5720a38cfe)
Solutions
- Re-fetch the certificate: generate a new token, call conduit.getcertificate with it, and use the returned certificate.
- Verify the client signs exactly sha1((string)token . certificate) with the same token it sends as authToken.
- If problems persist, confirm clocks (skew produces ERR-INVALID-TOKEN, not this error) and that the username matches the certificate owner.
Example fix
# before: stale cached certificate $ rm -f ~/.arcrc && arc install-certificate <token> # after: arc fetches and stores the current certificate, then $ arc call-conduit user.whoami
Defensive patterns
Strategy: try-catch
Try / catch
try {
$result = $call->execute();
} catch (ConduitException $ex) {
if ($ex->getMessage() === 'ERR-INVALID-CERTIFICATE') {
// Drop cached credentials and re-run the certificate handshake once.
}
} Prevention
- Always mint a fresh token and fetch the certificate in the same run; never cache certificates across days.
- Compute the signature as exactly sha1((string)$token . $certificate).
- Test client clocks separately: skew yields ERR-INVALID-TOKEN, not this error.
When it happens
Trigger: Client cached an old certificate after it was rotated/regenerated; signature computed over a different concatenation or encoding than sha1(token + certificate); mixing one user's token with another user's certificate.
Common situations: Stale ~/.arcrc credentials after an admin regenerated conduit certificates; hand-rolled clients reimplementing the handshake and getting the concatenation order wrong.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- ERR-NO-CERTIFICATE
- ERR-INVALID-USER
- ERR-RATE-LIMIT
- ERR-BAD-TOKEN
- Certificate token points to an invalid user!
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/830920bbda9d1d55.
Report an issue: GitHub.