BloopAI/vibe-kanban · critical

Server proof verification failed.

Error message

Server proof verification failed.

What it means

During PAKE-based relay host pairing, pairRelayHost runs a SPAKE2 enrollment with the relay backend; after the finish step it verifies the server's proof against the derived shared key. This Error is thrown when verifyServerProof returns false, meaning the server's server_proof_b64 does not match what the client expects — the server could not prove it derived the same shared secret (or the messages were tampered with / mismatched protocol versions).

Source

Thrown at packages/web-core/src/shared/dialogs/settings/settings/useRelayRemoteHostMutations.ts:96

      client_id: relayClientIdentity.clientId,
      client_name: relayClientIdentity.clientName,
      client_browser: relayClientIdentity.clientBrowser,
      client_os: relayClientIdentity.clientOs,
      client_device: relayClientIdentity.clientDevice,
      public_key_b64: publicKeyB64,
      client_proof_b64: clientProofB64,
    }
  );

  const serverProofValid = await verifyServerProof(
    sharedKey,
    startData.enrollment_id,
    publicKeyBytes,
    finishData.server_public_key_b64,
    finishData.server_proof_b64
  );
  if (!serverProofValid) {
    throw new Error('Server proof verification failed.');
  }

  await savePairedRelayHost({
    host_id: hostId,
    host_name: hostName,
    client_id: relayClientIdentity.clientId,
    client_name: relayClientIdentity.clientName,
    signing_session_id: finishData.signing_session_id,
    public_key_b64: publicKeyB64,
    private_key_jwk: privateKeyJwk,
    server_public_key_b64: finishData.server_public_key_b64,
    paired_at: new Date().toISOString(),
  });
}

export function useRelayRemoteHostsQuery() {
  return {
    queryKey: RELAY_REMOTE_HOSTS_QUERY_KEY,

View on GitHub (pinned to 4deb7eca8f)

Solutions

  1. Re-enter the pairing code carefully (or regenerate it on the host) and retry the pairing flow
  2. Verify the relay backend and the client are on compatible versions — upgrade the older side
  3. Check that no proxy/HTTPS interceptor is rewriting or caching the enrollment responses
  4. Clear stored paired-host state and start a fresh pairing session

Example fix

// before
const serverProofValid = await verifyServerProof(
  sharedKey, startData.enrollment_id, publicKeyBytes,
  finishData.server_public_key_b64, finishData.server_proof_b64
);
if (!serverProofValid) {
  throw new Error('Server proof verification failed.');
}
// after
const serverProofValid = await verifyServerProof(
  sharedKey, startData.enrollment_id, publicKeyBytes,
  finishData.server_public_key_b64, finishData.server_proof_b64
);
if (!serverProofValid) {
  throw new Error(
    `Server proof verification failed for host ${hostId} ` +
    '(check that the pairing code matches and host/client relay versions are compatible).'
  );
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Before pairing: ensure code normalization matches and host exists
const normalized = normalizedCode.trim().replace(/[-\s]/g, '').toUpperCase();
if (normalized.length === 0) throw new Error('Pairing code is empty');
const hosts = await listRelayHosts();
if (!hosts.some((h) => h.id === hostId)) throw new Error('Unknown host');

Type guard

function isPairingFailure(e: unknown): e is Error & { step: 'server-proof' } {
  return e instanceof Error && e.message.includes('Server proof verification failed');
}

Try / catch

try {
  await pairRelayHost({ hostId, hostName, normalizedCode });
} catch (e) {
  if (isPairingFailure(e)) {
    // Do NOT save the host; prompt user to re-enter the code and retry.
    showPairingError('Pairing code mismatch or incompatible host version. Please retry.');
  }
}

Prevention

When it happens

Trigger: Calling usePairRemoteCloudHostMutation with a hostId/hostName/normalizedCode where finishRelaySpake2Enrollment returns a server proof that fails verification: wrong or mistyped enrollment code variant, mismatched relay backend/client SPAKE2 implementations or versions, corrupted/intercepted server_message data, or pairing against a host whose session state expired between start and finish.

Common situations: Typo in the pairing code (code normalized differently on the two sides); pairing an older host running an incompatible relay protocol version; a man-in-the-middle or misconfigured relay proxy altering payloads; race where the enrollment session on the relay expired before finish was called.

Related errors


AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29). Data as JSON: /api/errors/3e9fad2182a3e04b. Report an issue: GitHub.