commaai/openpilot · error · RuntimeError

SetNickname failed with status 0x{code:02X}

Error message

SetNickname failed with status 0x{code:02X}

What it means

set_profile_nickname() maps the eUICC's SetNickname status byte: 0x00 success, 0x01 not-found (separate error), anything else raises RuntimeError with the raw status code in hex. These residual codes are undefined/unclassified eUICC rejections — e.g. insufficient memory or eUICC-internal errors — that SGP.22 does not enumerate for this operation.

Source

Thrown at openpilot/common/esim/lpa.py:409

    return []
  return [decode_struct(value, PROFILE) for tag, value in iter_tlv(list_ok) if tag == 0xE3]


def list_profiles(client: AtClient) -> list[dict]:
  return decode_profiles(es10x_command(client, TAG_PROFILE_INFO_LIST.to_bytes(2, "big") + b"\x00"))


def set_profile_nickname(client: AtClient, iccid: str, nickname: str) -> None:
  nickname_bytes = nickname.encode("utf-8")
  if len(nickname_bytes) > 64:
    raise ValueError("Profile nickname must be 64 bytes or less")
  content = encode_tlv(TAG_ICCID, string_to_tbcd(iccid)) + encode_tlv(0x90, nickname_bytes)
  response = es10x_command(client, encode_tlv(TAG_SET_NICKNAME, content))
  code = require_tag(require_tag(response, TAG_SET_NICKNAME, "SetNicknameResponse"), TAG_STATUS, "SetNickname status")[0]
  if code == 0x01:
    raise LPAError(f"profile {iccid} not found")
  if code != 0x00:
    raise RuntimeError(f"SetNickname failed with status 0x{code:02X}")


# --- ES9P HTTP ---

def es9p_request(smdp_address: str, endpoint: str, payload: dict, error_prefix: str = "Request", session: requests.Session | None = None) -> dict:
  url = f"https://{smdp_address}/gsma/rsp2/es9plus/{endpoint}"
  headers = {"User-Agent": "gsma-rsp-lpad", "X-Admin-Protocol": "gsma/rsp/v2.3.0", "Content-Type": "application/json"}
  http = session or requests
  resp = http.post(url, json=payload, headers=headers, timeout=HTTP_TIMEOUT, verify=GSMA_CI_BUNDLE)
  resp.raise_for_status()
  if not resp.content:
    return {}
  data = resp.json()
  if "header" in data and "functionExecutionStatus" in data["header"]:
    status = data["header"]["functionExecutionStatus"]
    if status.get("status") == "Failed":
      sd = status.get("statusCodeData", {})
      reason = sd.get("reasonCode", "unknown")

View on GitHub (pinned to 516ec1e682)

Solutions

  1. Retry once after reopening the ISD-R channel — transient eUICC states (catBusy-like) can produce nonzero statuses
  2. Dump the raw response with DEBUG=1 and compare against the eUICC's SGP.22 version; treat unknown codes as firmware-specific
  3. If persistent, power-cycle the modem/eUICC and retry the nickname update
Defensive patterns

Strategy: retry

Try / catch

try:
  set_profile_nickname(client, iccid, name)
except RuntimeError as e:
  if 'SetNickname failed with status' in str(e):
    client.channel = None
    client.open_isdr()
    set_profile_nickname(client, iccid, name)  # single retry after channel reset
  else:
    raise

Prevention

When it happens

Trigger: The eUICC answers the nickname request with a status other than 0x00/0x01: eUICC memory pressure, nonstandard firmware returning vendor-specific codes, or a corrupted response whose status byte is garbage.

Common situations: Low-end or test eUICCs with partial SGP.22 implementations; eUICC in a bad state after a failed install; status byte misparsed because the TLV layout differs from expected.

Related errors


AI-assisted analysis of commaai/openpilot@516ec1e682 (2026-08-15). Data as JSON: /api/errors/64299117fc26a761. Report an issue: GitHub.