commaai/openpilot · critical · Exception

Raw hash mismatch '{raw_hash.hexdigest().lower()}'

Error message

Raw hash mismatch '{raw_hash.hexdigest().lower()}'

What it means

After uncompressing and unsparsifying a partition image, verify/flash code compares the SHA-256 of the raw (unsparsified) output against partition['hash_raw']. A mismatch means the bytes written differ from the manifest — corruption in the sparse stream, truncation, or a wrong/man-in-the-middled download.

Source

Thrown at openpilot/common/hardware/comma/agnos.py:176

def extract_compressed_image(target_slot_number: int, partition: dict, cloudlog):
  path = get_partition_path(target_slot_number, partition)
  downloader = StreamingDecompressor(partition['url'])

  with open(path, 'wb+') as out:
    # Flash partition
    last_p = 0
    raw_hash = hashlib.sha256()
    f = unsparsify if partition['sparse'] else noop
    for chunk in f(downloader):
      raw_hash.update(chunk)
      out.write(chunk)
      p = int(out.tell() / partition['size'] * 100)
      if p != last_p:
        last_p = p
        print(f"Installing {partition['name']}: {p}", flush=True)

    if raw_hash.hexdigest().lower() != partition['hash_raw'].lower():
      raise Exception(f"Raw hash mismatch '{raw_hash.hexdigest().lower()}'")

    if downloader.sha256.hexdigest().lower() != partition['hash'].lower():
      raise Exception("Uncompressed hash mismatch")

    if out.tell() != partition['size']:
      raise Exception("Uncompressed size mismatch")

    os.sync()


def flash_partition(target_slot_number: int, partition: dict, cloudlog, standalone=False):
  cloudlog.info(f"Downloading and writing {partition['name']}")

  if verify_partition(target_slot_number, partition):
    cloudlog.info(f"Already flashed {partition['name']}")
    return

  # Clear hash before flashing in case we get interrupted

View on GitHub (pinned to 516ec1e682)

Solutions

  1. Retry the AGNOS flash — transient corruption is the most common cause
  2. Check network reliability / use a wired or stable connection for large firmware downloads
  3. Ensure the manifest and images come from the same release (no partial update)
Defensive patterns

Strategy: retry

Try / catch

for attempt in range(3):
    try:
        flash_partition(slot, partition, cloudlog)
        break
    except Exception as e:
        if "mismatch" not in str(e):
            raise

Prevention

When it happens

Trigger: verify_partition()/flash_partition() where the unsparsified output hash differs from the manifest's hash_raw — e.g. a chunk was dropped or reordered by the streaming decompressor.

Common situations: Corrupted download over flaky network; partial write after power loss; manifest and image versions out of sync.

Related errors


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