#935·mvt

check-bugreport exits 0 with an empty result on a MIUI / HyperOS wrapper archive

Author: va-residentCreated Sep 18, 2026Updated Sep 18, 2026

Version: 2026.9.15.dev4+g7973e90 (main at 7973e90), installed with pip install -e . Environment: Python 3.14.7, macOS 26.5 (arm64) Command: mvt-android check-bugreport -o out <bugreport.zip>

Steps to reproduce

  1. Take a bug report saved from a Xiaomi-family phone (MIUI / HyperOS, any Android 11–16). What the phone hands over is a zip of app logs, ANR traces and tcpdump captures with the real bug report nested inside it:

    com.<vendor>.<app>-appLog/0/data/data/…/debug_log/…       ← app logs
    bugreport-<device>-<timestamp>.zip                        ← the actual bug report
  2. Run check-bugreport on that outer zip.

Expected

Either the bug report is parsed, or the command says it could not find one.

Actual

The command finishes in about a second, exits 0, and writes an output directory containing info.json, alerts_timeline.csv and command.log and nothing else. No error is raised. From the output alone this is indistinguishable from a bug report that genuinely contained nothing.

from_zip() lists only the outer members, and BugReportModule._get_dumpstate_file() looks for main_entry.txt, dumpState_*.log or */dumpsys.txt — none of which exist at that level, so every module reports it found no files.

How often, and what is lost

Measured on 44 bug report collections — 14 wrapper archives (12 distinct builds, all Xiaomi-family, Android 11–16) and 30 normal collections as controls (14 brands, Android 10–16):

upstream main
13 of the 14 wrappers 0 artifacts, 0 records, exit 0
the 14th one tombstones.json with 4 records — tombstones are found by file pattern in the outer archive, so a wrapper can look "partly parsed"
reading the nested archive instead 260 artifacts, 586 638 records, 109 502 timeline rows, 94 alerts

Note for whoever fixes it

27 of the 30 normal collections also contain some other .zip member (screen recordings, proto bundles, vendor logs), so the descent has to be gated on "no entry point at this level", not on "a zip is present". In the 14 wrappers the bug report is the only zip member in 13 and one of two in the fourteenth.

Fix

I have a working fix with tests, verified on all 14 wrappers and the 30 controls. Happy to open the PR — tell me whether you would rather have the descent in cmd_check_bugreport.py where the archive is opened, or in BugReportModule next to _get_dumpstate_file().