commaai/openpilot · warning · ValueError

Profile nickname must be 64 bytes or less

Error message

Profile nickname must be 64 bytes or less

What it means

set_profile_nickname() validates the UTF-8 byte length of the nickname before encoding the ES10x SetNickname request. SGP.22 limits the nickname field to 64 bytes; exceeding it raises ValueError client-side without ever touching the modem.

Source

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

}


def decode_profiles(blob: bytes) -> list[dict]:
  root = require_tag(blob, TAG_PROFILE_INFO_LIST, "ProfileInfoList")
  list_ok = find_tag(root, TAG_OK)
  if list_ok is None:
    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:

View on GitHub (pinned to 516ec1e682)

Solutions

  1. Truncate by bytes, not characters, before calling: encode to UTF-8, slice to 64 bytes avoiding splitting a multibyte char
  2. Strip/shorten the input at the UI layer with a byte-length counter
  3. ASCII-ify or abbreviate long identifiers before using them as nicknames

Example fix

# before
set_profile_nickname(client, iccid, '🚗 my awesome super long vehicle name with emoji 🚗')
# ValueError: Profile nickname must be 64 bytes or less

# after
def fit_nickname(name: str, limit: int = 64) -> str:
  raw = name.encode('utf-8')
  while len(raw) > limit:
    name = name[:-1]
    raw = name.encode('utf-8')
  return name

set_profile_nickname(client, iccid, fit_nickname(user_input))
Defensive patterns

Strategy: validation

Validate before calling

def valid_nickname(name: str) -> bool:
  return len(name.encode('utf-8')) <= 64

assert valid_nickname(candidate), 'nickname exceeds 64 UTF-8 bytes'

Type guard

def is_valid_nickname(name: str) -> bool:
  return 0 < len(name.encode('utf-8')) <= 64

Try / catch

try:
  set_profile_nickname(client, iccid, name)
except ValueError as e:
  if '64 bytes' in str(e):
    set_profile_nickname(client, iccid, name.encode('utf-8')[:64].decode('utf-8', errors='ignore'))
  else:
    raise

Prevention

When it happens

Trigger: Calling set_profile_nickname(client, iccid, nickname) with nickname.encode('utf-8') longer than 64 bytes. Multibyte characters (emoji, CJK, accents) count per byte, so a 25-emoji nickname already exceeds 64 bytes even though it is 25 'characters'.

Common situations: Passing user-typed names/vehicle names from a UI without length checks; assuming the limit is 64 characters rather than 64 bytes; concatenating device identifiers into the nickname.

Related errors


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