commaai/openpilot · error · RuntimeError
Missing {label or f'tag 0x{target:X}'}
Error message
Missing {label or f'tag 0x{target:X}'} What it means
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.
Source
Thrown at openpilot/common/esim/lpa.py:302
if idx + num_bytes > length:
break
size = int.from_bytes(data[idx : idx + num_bytes], "big")
idx += num_bytes
if idx + size > length:
break
value = data[idx : idx + size]
idx += size
yield (tag_value, value, start_pos, idx) if with_positions else (tag_value, value)
def find_tag(data: bytes, target: int) -> bytes | None:
return next((v for t, v in iter_tlv(data) if t == target), None)
def require_tag(data: bytes, target: int, label: str = "") -> bytes:
v = find_tag(data, target)
if v is None:
raise RuntimeError(f"Missing {label or f'tag 0x{target:X}'}")
return v
def tbcd_to_string(raw: bytes) -> str:
return "".join(str(n) for b in raw for n in (b & 0x0F, b >> 4) if n <= 9)
def string_to_tbcd(s: str) -> bytes:
digits = [int(c) for c in s if c.isdigit()]
return bytes(digits[i] | ((digits[i + 1] if i + 1 < len(digits) else 0xF) << 4) for i in range(0, len(digits), 2))
def encode_tlv(tag: int, value: bytes) -> bytes:
tag_bytes = bytes([(tag >> 8) & 0xFF, tag & 0xFF]) if tag > 255 else bytes([tag])
vlen = len(value)
if vlen <= 127:
return tag_bytes + bytes([vlen]) + value
length_bytes = vlen.to_bytes((vlen.bit_length() + 7) // 8, "big")View on GitHub (pinned to 516ec1e682)
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
Example fix
# before
status = require_tag(response, TAG_STATUS, 'SetNickname status')[0]
# RuntimeError: Missing SetNickname status
# after — tolerate optional absence, fail with context
from openpilot.common.esim.lpa import find_tag, TAG_STATUS
status = find_tag(response, TAG_STATUS)
if status is None:
raise RuntimeError(f'unexpected eUICC response layout: {response.hex()}')
code = status[0] Defensive patterns
Strategy: try-catch
Try / catch
from openpilot.common.esim.lpa import require_tag, RuntimeError
try:
value = require_tag(data, TAG_STATUS, 'status')
except RuntimeError as e:
if str(e).startswith('Missing'):
log.error('unexpected eUICC response: %s', data.hex())
client.channel = None
client.open_isdr() # retry from a clean channel
raise Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Invalid BoundProfilePackage
- APDU failed with SW={sw1:02X}{sw2:02X}
- Profile nickname must be 64 bytes or less
- profile {iccid} not found
- SetNickname failed with status 0x{code:02X}
AI-assisted analysis of commaai/openpilot@516ec1e682 (2026-08-15).
Data as JSON: /api/errors/ffc255798bd5593b.
Report an issue: GitHub.