{"record":{"id":"3730cb56911f752f","repo":"commaai/openpilot","slug":"unable-to-parse-url","errorCode":null,"errorMessage":"Unable to parse: {url}","messagePattern":"Unable to parse: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"openpilot/tools/lib/bootlog.py","lineNumber":16,"sourceCode":"import functools\nimport re\n\nfrom openpilot.tools.lib.auth_config import get_token\nfrom openpilot.tools.lib.api import CommaApi\nfrom openpilot.tools.lib.helpers import RE\n\n\n@functools.total_ordering\nclass Bootlog:\n  def __init__(self, url: str):\n    self._url = url\n\n    r = re.search(RE.BOOTLOG_NAME, url)\n    if not r:\n      raise Exception(f\"Unable to parse: {url}\")\n\n    self._id = r.group('log_id')\n    self._dongle_id = r.group('dongle_id')\n\n  @property\n  def url(self) -> str:\n    return self._url\n\n  @property\n  def dongle_id(self) -> str:\n    return self._dongle_id\n\n  @property\n  def id(self) -> str:\n    return self._id\n\n  def __str__(self):\n    return f\"{self._dongle_id}/{self._id}\"","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/commaai/openpilot/blob/516ec1e68203439a73f340f1d0b3b91eabc626ee/openpilot/tools/lib/bootlog.py#L1-L34","documentation":"Bootlog.__init__ parses a bootlog URL/name with the RE.BOOTLOG_NAME regex (which equals ROUTE_NAME: {dongle_id}[|_/]{log_id}). If the string does not match that pattern, the URL cannot be split into dongle_id and log_id and the Bootlog cannot be constructed. It is strict input validation on bootlog identifiers.","triggerScenarios":"Constructing Bootlog(url) with a full https URL whose path does not contain a parseable name, a filename like 'boot-xxxx.zip', or a raw segment name 'dongle|--00-00-00--0'; passing a dongle id alone or garbage text.","commonSituations":"Iterating a directory of bootlogs that includes non-bootlog files; renaming bootlog files; copy-pasting a truncated name; separators not in the accepted set ('|', '_', '/').","solutions":["Pass the canonical name, e.g. '0000000000000000|2024-01-15--10-30-00' or a URL containing that substring","When scanning directories, filter candidates through the same regex (re.search(RE.BOOTLOG_NAME, name)) before constructing Bootlog","Verify the dongle id is the full hex id and the timestamp keeps the YYYY-MM-DD--HH-MM-SS shape"],"exampleFix":"# before\nBootlog('bootlog_2024.zip')\n\n# after\nfrom openpilot.tools.lib.helpers import RE\nname = 'b0c9d232tripid|2024-01-15--10-30-00'\nif re.search(RE.BOOTLOG_NAME, name):\n    bootlog = Bootlog(name)","handlingStrategy":"type-guard","validationCode":"import re\nfrom openpilot.tools.lib.helpers import RE\nif not re.search(RE.BOOTLOG_NAME, candidate):\n    raise SystemExit(f\"{candidate!r} is not a parseable bootlog name (need dongleid|YYYY-MM-DD--HH-MM-SS)\")","typeGuard":"import re\nfrom openpilot.tools.lib.helpers import RE\n\ndef is_bootlog_name(url: str) -> bool:\n    \"\"\"True when the string contains a route/bootlog-shaped identifier.\"\"\"\n    return isinstance(url, str) and re.search(RE.BOOTLOG_NAME, url) is not None","tryCatchPattern":"try:\n    bl = Bootlog(url)\nexcept Exception as e:\n    if 'Unable to parse' in str(e):\n        continue  # skip non-bootlog files when scanning a directory\n    raise","preventionTips":["Filter directory listings with the same RE.BOOTLOG_NAME regex before constructing Bootlog objects","Keep bootlog names canonical (dongle_id + '|' + timestamp); avoid renaming archives away from that shape"],"tags":["bootlog","regex","validation","route-data","openpilot"],"backgroundTag":null,"analyzedSha":"516ec1e68203439a73f340f1d0b3b91eabc626ee","analyzedAt":"2026-08-15T00:17:37.461Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}