commaai/openpilot · error · RuntimeError
AuthenticateServer rejected by eUICC: {AUTH_SERVER_ERROR_COD
Error message
AuthenticateServer rejected by eUICC: {AUTH_SERVER_ERROR_CODES.get(code, 'unknown')} (0x{code:02X}) What it means
authenticate_server() sends the ES10b AuthenticateServer command (SM-DP+ signed data, signature, cert) to the eUICC. If the response contains tag 0xA1 instead of a success payload, the eUICC refused authentication and the integer code is mapped through AUTH_SERVER_ERROR_CODES (e.g. 0x05 invalidServerSignature, 0x0A matchingIdRefused, 0x10 insufficientMemory); unmapped codes print 'unknown'.
Source
Thrown at openpilot/common/esim/lpa.py:489
challenge_resp = es10x_command(client, encode_tlv(TAG_EUICC_CHALLENGE, b""))
challenge = require_tag(require_tag(challenge_resp, TAG_EUICC_CHALLENGE, "GetEuiccDataResponse"),
TAG_STATUS, "challenge in response")
info_resp = es10x_command(client, encode_tlv(TAG_EUICC_INFO, b""))
require_tag(info_resp, TAG_EUICC_INFO, "GetEuiccInfo1Response")
return challenge, info_resp
def authenticate_server(client: AtClient, b64_signed1: str, b64_sig1: str, b64_pk_id: str, b64_cert: str, matching_id: str) -> str:
tac = bytes([0x35, 0x29, 0x06, 0x11])
device_info = encode_tlv(TAG_STATUS, tac) + encode_tlv(0xA1, b"")
ctx_inner = encode_tlv(TAG_STATUS, matching_id.encode("utf-8")) + encode_tlv(0xA1, device_info)
content = b64d(b64_signed1) + b64d(b64_sig1) + b64d(b64_pk_id) + b64d(b64_cert) + encode_tlv(0xA0, ctx_inner)
response = es10x_command(client, encode_tlv(TAG_AUTH_SERVER, content))
root = require_tag(response, TAG_AUTH_SERVER, "AuthenticateServerResponse")
error_tag = find_tag(root, 0xA1)
if error_tag is not None:
code = int.from_bytes(error_tag, "big") if error_tag else 0
raise RuntimeError(f"AuthenticateServer rejected by eUICC: {AUTH_SERVER_ERROR_CODES.get(code, 'unknown')} (0x{code:02X})")
return b64e(response)
def prepare_download(client: AtClient, b64_signed2: str, b64_sig2: str, b64_cert: str, cc: str | None = None) -> str:
smdp_signed2 = b64d(b64_signed2)
smdp_signature2 = b64d(b64_sig2)
smdp_certificate = b64d(b64_cert)
smdp_signed2_root = find_tag(smdp_signed2, 0x30)
if smdp_signed2_root is None:
raise RuntimeError("Invalid smdpSigned2")
transaction_id = find_tag(smdp_signed2_root, TAG_STATUS)
cc_required_flag = find_tag(smdp_signed2_root, 0x01)
if transaction_id is None or cc_required_flag is None:
raise RuntimeError("Invalid smdpSigned2")
content = smdp_signed2 + smdp_signature2
if int.from_bytes(cc_required_flag, "big") != 0:
if not cc:
raise RuntimeError("Confirmation code required but not provided")View on GitHub (pinned to 516ec1e682)
Solutions
- Map the hex code: 0x01 eUICC verification failed, 0x02/0x03 eUICC cert expired/revoked (hardware issue, replace eSIM), 0x05 invalid server signature (server/carrier problem), 0x0A matchingId refused (wrong or used QR), 0x10 insufficient memory (delete profiles)
- For 0x0A: request a fresh QR code; the current one is bound to another session/device
- For 0x10: delete unused profiles to free eUICC memory, then retry download
- For 0x05/0x06: retry later or escalate to the carrier; also verify device clock is correct (cert validation is time-sensitive)
Example fix
# before
b64_auth = authenticate_server(client, s1, sig1, pkid, cert, matching_id)
# RuntimeError: AuthenticateServer rejected by eUICC: matchingIdRefused (0x0A)
# after
from openpilot.common.esim.lpa import authenticate_server
try:
b64_auth = authenticate_server(client, s1, sig1, pkid, cert, matching_id)
except RuntimeError as e:
if '(0x0A)' in str(e):
raise SystemExit('QR code matching ID refused; get a new QR code from carrier') from e
if '(0x10)' in str(e):
raise SystemExit('eUICC memory full; delete profiles and retry') from e
raise Defensive patterns
Strategy: try-catch
Validate before calling
from openpilot.common.esim.lpa import list_profiles
# pre-flight: free memory for 0x10, valid QR for 0x0A
if len(list_profiles(client)) >= max_profiles_supported:
raise SystemExit('eUICC near memory limit; delete profiles before download') Try / catch
try:
b64_auth = authenticate_server(client, s1, sig1, pkid, cert, matching_id)
except RuntimeError as e:
code = str(e).rsplit('0x', 1)[-1]
if code == '0A':
raise SystemExit('QR matching ID refused; obtain fresh QR') from e
if code == '10':
raise SystemExit('eUICC memory full; delete profiles') from e
if code in ('02', '03'):
raise SystemExit('eUICC certificate issue; hardware replacement needed') from e
raise Prevention
- Use each QR activation code exactly once and keep the matching ID intact
- Check eUICC free memory before downloads on devices with many profiles
- Ensure system time is valid — certificate validation depends on it
When it happens
Trigger: During profile download when the eUICC rejects the SM-DP+: server signature invalid (0x05), eUICC certificate expired/revoked (0x02/0x03), matching ID from the QR refused (0x0A), eUICC GSMA CI public key unknown (0x06), or insufficient eUICC memory (0x10).
Common situations: QR code whose matchingId doesn't match the reserved profile (wrong QR / already consumed elsewhere); carrier server certificate/signature issues; test eUICCs with expired certificates; eUICC memory full from many installed profiles.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- APDU failed with SW={sw1:02X}{sw2:02X}
- SetNickname failed with status 0x{code:02X}
- Invalid BoundProfilePackage
- Profile installation failed: no result from eUICC
- Missing {label or f'tag 0x{target:X}'}
AI-assisted analysis of commaai/openpilot@516ec1e682 (2026-08-15).
Data as JSON: /api/errors/47e74a4bb4bc99a9.
Report an issue: GitHub.