commaai/openpilot · critical · Exception

Uncompressed hash mismatch

Error message

Uncompressed hash mismatch

What it means

The compressed bytes received from the downloader are hashed (downloader.sha256) and compared against partition['hash']. A mismatch means the compressed stream itself is corrupted even before decompression — network corruption, proxy mangling, or a stale/cached partial file.

Source

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

  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
  full_check = partition['full_check']
  if not full_check:
    clear_partition_hash(target_slot_number, partition)

View on GitHub (pinned to 516ec1e682)

Solutions

  1. Retry the download (the retry loop already handles RequestException; hash mismatch should be retried too)
  2. Verify the manifest URL and hash are from the same AGNOS release
  3. Rule out intercepting proxies or modified TLS appliances on the network
Defensive patterns

Strategy: retry

Try / catch

# extend the existing retry loop to catch hash mismatches, not just RequestException
except (requests.exceptions.RequestException, Exception) as e:
    if 'hash mismatch' not in str(e):
        raise
    time.sleep(10)

Prevention

When it happens

Trigger: flash_partition where the downloaded (still-compressed) stream hash differs from the manifest hash — truncated HTTP response, corrupt gzip/bzip stream, or wrong URL.

Common situations: Flaky Wi-Fi during multi-hundred-MB firmware download; interrupted resume serving partial content; CDN/cache serving a corrupted artifact.

Related errors


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