{"record":{"id":"7229d7e8f2d2beed","repo":"dotnet/runtime","slug":"error-unclean-replay","errorCode":null,"errorMessage":"Error, unclean replay.","messagePattern":"Error, unclean replay\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"src/coreclr/scripts/superpmi.py","lineNumber":1479,"sourceCode":"\n        if not os.path.isfile(self.toc_file):\n            raise RuntimeError(\"Error, toc file not created correctly at: %s\" % self.toc_file)\n\n    def __verify_final_mch__(self):\n        \"\"\" Verify the resulting MCH file is error-free when running SuperPMI against it with the same JIT used for collection.\n\n        Notes:\n            <SuperPmiPath> -p -f <s_finalFailMclFile> <s_finalMchFile> <jitPath>\n        \"\"\"\n\n        logging.info(\"Verifying MCH file\")\n\n        mch_files = [ self.final_mch_file ]\n        spmi_replay = SuperPMIReplay(self.coreclr_args, mch_files, self.jit_path)\n        passed = spmi_replay.replay()\n\n        if not passed:\n            raise RuntimeError(\"Error, unclean replay.\")\n\n    def __process_for_ci__(self):\n        \"\"\" Helix doesn't upload zero-sized files. Sometimes we end up with zero-sized .mch files if\n            there is no data collected. Convert these to special \"sentinel\" files that are later processed\n            by \"merge-mch\" by deleting them. This prevents the <HelixWorkItem.DownloadFilesFromResults>\n            file download to succeed (because the file exists) and the MCH merge to also succeed.\n        \"\"\"\n\n        logging.info(\"Process MCH files for CI\")\n\n        if os.path.getsize(self.final_mch_file) == 0:\n            # Convert to sentinel file\n            logging.info(\"Converting zero-length MCH file {} to ZEROLENGTH sentinel file\".format(self.final_mch_file))\n            with open(self.final_mch_file, \"w\") as write_fh:\n                write_fh.write(\"ZEROLENGTH\")\n\n################################################################################\n# SuperPMI Replay helpers","sourceCodeStart":1461,"sourceCodeEnd":1497,"githubUrl":"https://github.com/dotnet/runtime/blob/60108ba66eb7d1d12f595480091b4ad80a24b172/src/coreclr/scripts/superpmi.py#L1461-L1497","documentation":"Raised by SuperPMICollection.__verify_final_mch__ when a SuperPMIReplay.replay() over the just-produced final MCH file does not pass cleanly. This is the collection integrity gate: the same JIT used for collection must replay every method context without diagnostics, otherwise the MCH is considered untrustworthy and the pipeline aborts. An unclean replay means the collected data would produce false results in future diff runs.","triggerScenarios":"Called during collection finalization when __verify_final_mch__ runs: it builds SuperPMIReplay(self.coreclr_args, [self.final_mch_file], self.jit_path) and calls replay(); if replay() returns False (SuperPMI reported failures or nonzero exit on one or more contexts), the RuntimeError fires. Occurs when the JIT being instrumented has a bug triggered during replay, when the collector shim and replay JIT mismatch, or when the MCH captured incomplete state.","commonSituations":"Testing an in-development JIT build that hits an assertion or fault during replay; a version skew between the superpmi-shim-collector used to gather and the clrjit used to verify; replaying a cross-arch MCH on the wrong host; transient OS-level failures (e.g. memory pressure) during replay.","solutions":["Inspect the SuperPMI log file (under spmi_location) for the specific method context(s) that failed replay and their error codes.","Re-run replay manually: '<superpmi_path> -p <final_mch_file> <jit_path>' to reproduce and capture the failing context.","Confirm the JIT (jit_path) and the collector shim come from the same build/Core_Root.","If the failure is an asserted JIT bug, file or attach to the JIT issue with the failing MCH context; if it is environmental, re-run with more memory/disk."],"exampleFix":"// before\nspmi_replay = SuperPMIReplay(self.coreclr_args, mch_files, self.jit_path)\npassed = spmi_replay.replay()\nif not passed:\n    raise RuntimeError(\"Error, unclean replay.\")\n// after\nspmi_replay = SuperPMIReplay(self.coreclr_args, mch_files, self.jit_path)\npassed = spmi_replay.replay()\nif not passed:\n    raise RuntimeError(f\"Unclean replay of {self.final_mch_file} with {self.jit_path}; see log {coreclr_args.log_file} for failing contexts\")","handlingStrategy":"try-catch","validationCode":"import os\ndef preflight_replay(final_mch_file, jit_path, superpmi_path):\n    for p in (final_mch_file, jit_path, superpmi_path):\n        if not os.path.isfile(p):\n            raise RuntimeError(f\"Replay preflight: missing {p}\")\n    if os.path.getsize(final_mch_file) == 0:\n        raise RuntimeError(\"MCH file is empty; nothing to replay\")","typeGuard":null,"tryCatchPattern":"try:\n    spmi_replay = SuperPMIReplay(self.coreclr_args, [self.final_mch_file], self.jit_path)\n    passed = spmi_replay.replay()\nexcept RuntimeError as e:\n    logging.error(\"Replay infrastructure error: %s\", e)\n    raise\nif not passed:\n    raise RuntimeError(f\"Unclean replay of {self.final_mch_file}; rerun manually: {self.superpmi_path} -p {self.final_mch_file} {self.jit_path}\")","preventionTips":["Use a JIT from the same build as the collector shim to avoid version skew.","Re-run replay manually on a failing MCH to isolate environmental from JIT bugs.","Capture the SuperPMI log to identify the exact failing method context."],"tags":["superpmi","replay","verification","jit","collection"],"backgroundTag":null,"analyzedSha":"60108ba66eb7d1d12f595480091b4ad80a24b172","analyzedAt":"2026-08-10T18:54:11.478Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}