commaai/openpilot · error · LPAProfileNotFoundError
profile not found: {iccid}
Error message
profile not found: {iccid} What it means
Lpa.delete_profile(iccid) looks up the requested ICCID in list_profiles(); if no profile matches, it raises LPAProfileNotFoundError with the requested ICCID. It indicates the eUICC has no such profile (or the ICCID string does not exactly match).
Source
Thrown at openpilot/common/esim/lpa.py:740
enabled=p.get("profileState") == "enabled",
provider=p.get("serviceProviderName") or "",
)
for p in list_profiles(self._client)
]
def get_active_profile(self) -> Profile | None:
return None
def process_notifications(self) -> None:
if not system_time_valid():
raise RuntimeError("System time is not set; TLS certificate validation requires a valid clock")
with self._acquire_channel():
process_notifications(self._client)
def delete_profile(self, iccid: str) -> None:
profile = next((p for p in self.list_profiles() if p.iccid == iccid), None)
if profile is None:
raise LPAProfileNotFoundError(f"profile not found: {iccid}")
if profile.is_comma:
raise LPAError("refusing to delete a comma profile")
with self._acquire_channel():
request = encode_tlv(TAG_DELETE_PROFILE, encode_tlv(TAG_ICCID, string_to_tbcd(iccid)))
response = es10x_command(self._client, request)
code = require_tag(require_tag(response, TAG_DELETE_PROFILE, "DeleteProfileResponse"), TAG_STATUS, "DeleteProfile status")[0]
if code != PROFILE_OK:
raise LPAError(f"DeleteProfile failed: {PROFILE_ERROR_CODES.get(code, 'unknown')} (0x{code:02X})")
def download_profile(self, qr: str, nickname: str | None = None) -> None:
with self._acquire_channel():
iccid = download_profile(self._client, qr)
if nickname and iccid:
set_profile_nickname(self._client, iccid, nickname)
def nickname_profile(self, iccid: str, nickname: str) -> None:
with self._acquire_channel():
set_profile_nickname(self._client, iccid, nickname)View on GitHub (pinned to 516ec1e682)
Solutions
- Call list_profiles() immediately before deleting and pass the exact iccid from that result
- Normalize the ICCID (strip spaces/dashes) before comparing
- Treat LPAProfileNotFoundError as a benign idempotent delete success where appropriate
Example fix
// before
delete_profile("89 00 12 34 ...")
// after
profiles = {p.iccid: p for p in lpa.list_profiles()}
if iccid in profiles:
lpa.delete_profile(iccid) Defensive patterns
Strategy: validation
Validate before calling
iccid = iccid.replace(" ", "").replace("-", "")
exists = any(p.iccid == iccid for p in lpa.list_profiles()) Try / catch
try:
lpa.delete_profile(iccid)
except LPAProfileNotFoundError:
pass # already gone — treat as success Prevention
- Always derive the ICCID from a fresh list_profiles() call
- Treat not-found on delete as idempotent success
When it happens
Trigger: Calling delete_profile with an ICCID from a stale cache, a typo, or one whose profile was already deleted; ICCID formatting differences (spaces/check digit) also fail the exact string comparison.
Common situations: UI lets the user act on a cached profile list that changed; ICCID copied with separators; profile removed on another device.
Related errors
- Profile installation failed at {cmd_name}: {err_name}
- Invalid profileMetadata
- Invalid activation code format
- System time is not set; TLS certificate validation requires
- refusing to delete a comma profile
AI-assisted analysis of commaai/openpilot@516ec1e682 (2026-08-15).
Data as JSON: /api/errors/ab12bf6dafb75fec.
Report an issue: GitHub.