{"record":{"id":"c5941d9e2af595c8","repo":"commaai/openpilot","slug":"confirmation-code-required-but-not-provided","errorCode":null,"errorMessage":"Confirmation code required but not provided","messagePattern":"Confirmation code required but not provided","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"openpilot/common/esim/lpa.py","lineNumber":507,"sourceCode":"    raise RuntimeError(f\"AuthenticateServer rejected by eUICC: {AUTH_SERVER_ERROR_CODES.get(code, 'unknown')} (0x{code:02X})\")\n  return b64e(response)\n\n\ndef prepare_download(client: AtClient, b64_signed2: str, b64_sig2: str, b64_cert: str, cc: str | None = None) -> str:\n  smdp_signed2 = b64d(b64_signed2)\n  smdp_signature2 = b64d(b64_sig2)\n  smdp_certificate = b64d(b64_cert)\n  smdp_signed2_root = find_tag(smdp_signed2, 0x30)\n  if smdp_signed2_root is None:\n    raise RuntimeError(\"Invalid smdpSigned2\")\n  transaction_id = find_tag(smdp_signed2_root, TAG_STATUS)\n  cc_required_flag = find_tag(smdp_signed2_root, 0x01)\n  if transaction_id is None or cc_required_flag is None:\n    raise RuntimeError(\"Invalid smdpSigned2\")\n  content = smdp_signed2 + smdp_signature2\n  if int.from_bytes(cc_required_flag, \"big\") != 0:\n    if not cc:\n      raise RuntimeError(\"Confirmation code required but not provided\")\n    content += encode_tlv(0x04, hashlib.sha256(hashlib.sha256(cc.encode(\"utf-8\")).digest() + transaction_id).digest())\n  content += smdp_certificate\n  response = es10x_command(client, encode_tlv(TAG_PREPARE_DOWNLOAD, content))\n  require_tag(response, TAG_PREPARE_DOWNLOAD, \"PrepareDownloadResponse\")\n  return b64e(response)\n\n\ndef _parse_tlv_header_len(data: bytes) -> int:\n  tag_len = 2 if data[0] & 0x1F == 0x1F else 1\n  length_byte = data[tag_len]\n  return tag_len + (1 + (length_byte & 0x7F) if length_byte & 0x80 else 1)\n\n\ndef _split_bpp(bpp: bytes) -> list[bytes]:\n  \"\"\"Split a BoundProfilePackage into APDU chunks per SGP.22 §5.7.6.\"\"\"\n  root_value = None\n  for tag, value, start, end in iter_tlv(bpp, with_positions=True):\n    if tag == TAG_BPP:","sourceCodeStart":489,"sourceCodeEnd":525,"githubUrl":"https://github.com/commaai/openpilot/blob/516ec1e68203439a73f340f1d0b3b91eabc626ee/openpilot/common/esim/lpa.py#L489-L525","documentation":"prepare_download() reads ccRequiredFlag from the server's smdpSigned2. When the flag is nonzero the SM-DP+ demands a confirmation code (the activation code's part after the '$$' in the QR, or one issued by the carrier). If the caller passed cc=None or an empty string in that case, RuntimeError is raised before any eUICC interaction.","triggerScenarios":"Downloading a profile whose QR/activation code includes a confirmation code (format ...$QRF-XXX$$CC123) but calling the download flow without extracting and passing the CC; carriers that always require a CC (e.g. some enterprise plans).","commonSituations":"QR string of the form LPA:1$rsp.example.com$ACTIVATION$$CODE where the code after $$ was stripped by the parser; interactive flows that didn't prompt; automation that ignores CC.","solutions":["Extract the confirmation code from the activation string: everything after the first '$$' in the QR code payload","Prompt the user for the CC when the carrier provided one separately (SMS/email)","Retry download passing the CC: download flow with cc='CODE' (via the CLI: append $$CODE in the QR argument if supported, or the API's cc parameter)"],"exampleFix":"# before\nprepare_download(client, b64_signed2, b64_sig2, b64_cert)  # cc=None\n# RuntimeError: Confirmation code required but not provided\n\n# after — parse CC from the QR activation string\nqr = 'LPA:1$rsp.truphone.com$QRF-TEST$$4321'\ncc = qr.split('$$', 1)[1] if '$$' in qr else None\nprepare_download(client, b64_signed2, b64_sig2, b64_cert, cc=cc)","handlingStrategy":"validation","validationCode":"def extract_confirmation_code(qr: str) -> str | None:\n  return qr.split('$$', 1)[1] if '$$' in qr else None\n\ncc = extract_confirmation_code(qr_string)\n# pass cc through to the download flow; server will still verify it","typeGuard":null,"tryCatchPattern":"try:\n  prepare_download(client, s2, sig2, cert, cc=cc)\nexcept RuntimeError as e:\n  if 'Confirmation code required' in str(e):\n    cc = input('carrier confirmation code: ').strip()\n    prepare_download(client, s2, sig2, cert, cc=cc)\n  else:\n    raise","preventionTips":["Parse the full QR activation string including the $$CC suffix at download start","Prompt interactively for CC whenever the carrier plan is known to require one","Don't strip '$$' segments during QR sanitization"],"tags":["esim","confirmation-code","qr-code","download","validation","python"],"backgroundTag":null,"analyzedSha":"516ec1e68203439a73f340f1d0b3b91eabc626ee","analyzedAt":"2026-08-15T00:17:37.461Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}