{"record":{"id":"ffc255798bd5593b","repo":"commaai/openpilot","slug":"missing-label-or-f-tag-0x-target-x","errorCode":null,"errorMessage":"Missing {label or f'tag 0x{target:X}'}","messagePattern":"Missing (.+?)'\\}","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"openpilot/common/esim/lpa.py","lineNumber":302,"sourceCode":"      if idx + num_bytes > length:\n        break\n      size = int.from_bytes(data[idx : idx + num_bytes], \"big\")\n      idx += num_bytes\n    if idx + size > length:\n      break\n    value = data[idx : idx + size]\n    idx += size\n    yield (tag_value, value, start_pos, idx) if with_positions else (tag_value, value)\n\n\ndef find_tag(data: bytes, target: int) -> bytes | None:\n  return next((v for t, v in iter_tlv(data) if t == target), None)\n\n\ndef require_tag(data: bytes, target: int, label: str = \"\") -> bytes:\n  v = find_tag(data, target)\n  if v is None:\n    raise RuntimeError(f\"Missing {label or f'tag 0x{target:X}'}\")\n  return v\n\n\ndef tbcd_to_string(raw: bytes) -> str:\n  return \"\".join(str(n) for b in raw for n in (b & 0x0F, b >> 4) if n <= 9)\n\n\ndef string_to_tbcd(s: str) -> bytes:\n  digits = [int(c) for c in s if c.isdigit()]\n  return bytes(digits[i] | ((digits[i + 1] if i + 1 < len(digits) else 0xF) << 4) for i in range(0, len(digits), 2))\n\n\ndef encode_tlv(tag: int, value: bytes) -> bytes:\n  tag_bytes = bytes([(tag >> 8) & 0xFF, tag & 0xFF]) if tag > 255 else bytes([tag])\n  vlen = len(value)\n  if vlen <= 127:\n    return tag_bytes + bytes([vlen]) + value\n  length_bytes = vlen.to_bytes((vlen.bit_length() + 7) // 8, \"big\")","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/commaai/openpilot/blob/516ec1e68203439a73f340f1d0b3b91eabc626ee/openpilot/common/esim/lpa.py#L284-L320","documentation":"require_tag() walks a BER-TLV structure looking for a specific tag and throws RuntimeError naming the missing tag (hex) or a human label like 'SetNickname status' when it is absent. It is the generic guard for malformed or unexpected eUICC/eSIM response payloads whose structure deviates from SGP.22 expectations.","triggerScenarios":"Any ES10x response parsing where the expected TLV element is missing: a SetNicknameResponse without its status tag, a ListNotificationResponse lacking the expected wrapper, or an eUICC returning truncated/noncompliant TLV. Also triggered if a response for a different command is passed in by mistake.","commonSituations":"eUICC firmware that is not fully SGP.22 compliant or is a newer/minor version with changed structure; response buffers truncated by ES10X_MSS=120 segmentation bugs; passing a raw response where a nested element was expected.","solutions":["Enable DEBUG=1 to dump the raw AT/+CGLA exchange and inspect the actual TLV bytes returned by the eUICC","Verify you are parsing the response that matches the command you sent (correct BFxx tag pair)","If the eUICC is noncompliant, use find_tag() with tolerant handling instead of require_tag() for optional elements","Reset modem/eUICC and retry — a corrupted APDU exchange (segmentation/61xx handling) can produce garbled responses that parse partially"],"exampleFix":"# before\nstatus = require_tag(response, TAG_STATUS, 'SetNickname status')[0]\n# RuntimeError: Missing SetNickname status\n\n# after — tolerate optional absence, fail with context\nfrom openpilot.common.esim.lpa import find_tag, TAG_STATUS\n\nstatus = find_tag(response, TAG_STATUS)\nif status is None:\n  raise RuntimeError(f'unexpected eUICC response layout: {response.hex()}')\ncode = status[0]","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"from openpilot.common.esim.lpa import require_tag, RuntimeError\n\ntry:\n  value = require_tag(data, TAG_STATUS, 'status')\nexcept RuntimeError as e:\n  if str(e).startswith('Missing'):\n    log.error('unexpected eUICC response: %s', data.hex())\n    client.channel = None\n    client.open_isdr()  # retry from a clean channel\n  raise","preventionTips":["Use find_tag + explicit None-handling for optional TLV elements; require_tag only for mandatory ones","Always hex-dump responses on parse failures to distinguish truncation from layout changes","Pin/verify eUICC SGP.22 version via euicc_info before parsing intricate structures"],"tags":["esim","tlv","parsing","sgp22","python"],"backgroundTag":null,"analyzedSha":"516ec1e68203439a73f340f1d0b3b91eabc626ee","analyzedAt":"2026-08-15T00:17:37.461Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}