commaai/openpilot · error · SystemExit

no profile at index {ref} (have {len(profiles)})

Error message

no profile at index {ref} (have {len(profiles)})

What it means

The esim CLI accepts a profile reference that is either a literal ICCID or a 1-based index into the alphabetically sorted (by ICCID) profile list. When the argument is all digits, it is treated as an index; if that index is out of range (idx < 0 or >= number of profiles), the script exits with SystemExit showing the list size.

Source

Thrown at openpilot/common/esim/esim.py:20

import argparse
import sys
import time
from openpilot.common.hardware import HARDWARE
from openpilot.common.esim.base import LPABase, Profile


def sorted_profiles(lpa: LPABase) -> list[Profile]:
  return sorted(lpa.list_profiles(), key=lambda p: p.iccid)


def resolve_iccid(lpa: LPABase, ref: str) -> str:
  # ref is either a 1-based index into the sorted list, or a literal iccid
  if ref.isdigit():
    profiles = sorted_profiles(lpa)
    idx = int(ref) - 1
    if not 0 <= idx < len(profiles):
      raise SystemExit(f'no profile at index {ref} (have {len(profiles)})')
    return profiles[idx].iccid
  return ref


def print_profiles(lpa: LPABase) -> None:
  profiles = sorted_profiles(lpa)
  print(f'\n{len(profiles)} profile{"s" if len(profiles) != 1 else ""}:')
  for i, p in enumerate(profiles, start=1):
    print(f'{i}. {p.iccid} (nickname: {p.nickname or "<none provided>"}) (provider: {p.provider}) - {"enabled" if p.enabled else "disabled"}')


def execute_and_process_notifications(lpa: LPABase, operation) -> None:
  try:
    operation()
  finally:
    time.sleep(1)  # Need to wait for 1s after the operation is finished so the eUICC/modem can settle down.
    try:
      lpa.process_notifications()

View on GitHub (pinned to 516ec1e682)

Solutions

  1. Run `esim.py list` first, note the current 1-based numbers and count, then reference a valid index within that count
  2. Pass the literal ICCID instead of an index — but only non-purely-digit forms avoid the index branch; since ICCIDs are numeric, prefer re-running `list` and using a valid index
  3. If the list is empty, download a profile before switching/deleting/renaming one
  4. Treat this SystemExit message as authoritative: it tells you exactly how many profiles exist

Example fix

# before
python -m openpilot.common.esim.esim switch 5   # only 2 profiles -> SystemExit

# after
python -m openpilot.common.esim.esim list
# 2 profiles:
# 1. 890000... (enabled)
# 2. 890111... (disabled)
python -m openpilot.common.esim.esim switch 2
Defensive patterns

Strategy: validation

Validate before calling

from openpilot.common.esim.esim import sorted_profiles

profiles = sorted_profiles(lpa)
idx = int(ref) if ref.isdigit() else None
if idx is not None and not 1 <= idx <= len(profiles):
  raise SystemExit(f'refresh profile list: only {len(profiles)} profiles, index {ref} invalid')

Try / catch

try:
  iccid = resolve_iccid(lpa, ref)
except SystemExit as e:
  print(f'invalid reference: {e}; run list to refresh')
  raise

Prevention

When it happens

Trigger: Running a command like `esim.py switch 3` or `esim.py delete 5 nickname` when the eUICC has fewer than that many profiles (e.g. 2 profiles and index 3, or index 0 / negative-looking values that parse via int()). Note a full ICCID is also all digits, so passing a real 19-20 digit ICCID that fits isdigit() can be misinterpreted as a huge index if it exceeds the profile count only in edge cases — in practice the index path triggers with short numeric args.

Common situations: User counts profiles from stale output (a profile was deleted since `list` was run); using 0-based indexing while the CLI expects 1-based; passing an ICCID string that is purely numeric and longer than the profile count is safe only if it matches len semantics — actually any digit string is treated as index, so passing a numeric ICCID always goes down the index branch.

Related errors


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