commaai/openpilot · error · LPAError
DeleteProfile failed: {PROFILE_ERROR_CODES.get(code, 'unknow
Error message
DeleteProfile failed: {PROFILE_ERROR_CODES.get(code, 'unknown')} (0x{code:02X}) What it means
Raised when the eUICC's DeleteProfile response carries a status code other than PROFILE_OK. The hex status and its name from PROFILE_ERROR_CODES are included (e.g. ICCID not found, profile enabled, eUICC memory error).
Source
Thrown at openpilot/common/esim/lpa.py:748
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)
def _enable_profile(self, iccid: str) -> int:
inner = encode_tlv(TAG_OK, encode_tlv(TAG_ICCID, string_to_tbcd(iccid)))
inner += b'\x01\x01\x01' # refreshFlag=1
response = es10x_command(self._client, encode_tlv(TAG_ENABLE_PROFILE, inner))
return require_tag(require_tag(response, TAG_ENABLE_PROFILE, "EnableProfileResponse"), TAG_STATUS, "EnableProfile status")[0]
def switch_profile(self, iccid: str) -> None:View on GitHub (pinned to 516ec1e682)
Solutions
- Disable/switch away from the profile before deleting it
- Retry with the exact ICCID from a fresh list_profiles()
- Process pending notifications, then retry — install notifications can block deletes on some eUICCs
Defensive patterns
Strategy: retry
Validate before calling
profile = next((p for p in lpa.list_profiles() if p.iccid == iccid), None)
if profile is not None and profile.enabled:
switch_or_disable_first() # eUICCs often refuse deleting enabled profiles Try / catch
try:
lpa.delete_profile(iccid)
except LPAError as e:
if "DeleteProfile failed" in str(e):
lpa.process_notifications()
lpa.delete_profile(iccid) # one retry after clearing notifications Prevention
- Disable profiles before deletion
- Process pending notifications before profile management operations
When it happens
Trigger: Calling delete_profile on an enabled profile (many eUICCs require disable first), an ICCID unknown to the eUICC, or while another profile operation holds the eUICC.
Common situations: Deleting the currently active/enabled profile; concurrent profile operations; stale ICCID after a profile switch.
Related errors
- EnableProfile failed: {PROFILE_ERROR_CODES.get(code, 'unknow
- Profile installation failed at {cmd_name}: {err_name}
- refusing to delete a comma profile
- APDU failed with SW={sw1:02X}{sw2:02X}
- SetNickname failed with status 0x{code:02X}
AI-assisted analysis of commaai/openpilot@516ec1e682 (2026-08-15).
Data as JSON: /api/errors/e5d0ebf724ff4227.
Report an issue: GitHub.