Inspect a damaged archive
You have an archive that fails verification, or one you do not trust, and you want to see exactly what is wrong without loading it into an application.
Sample.load uses the same bounded reader and refuses a damaged archive exactly as Mtrl.load() does, so this forensic route stays the recovery path.
This guide assumes: you have finished the tutorial path, including Save, load, and verify, and you know that verification reports several separate statuses rather than one yes/no answer.
Mtrl.load() refuses a damaged archive outright, which protects your data but tells you
little about the damage. forensic_inspect(path) is the read-only alternative: it examines
the bounded archive and returns a VerifyResult of facts — what is structurally sound,
which digests disagree, and which entries are affected — without ever returning the damaged
records as analysis inputs.
The example below saves a sound archive and inspects it, so you can see the shape of the report before you ever meet a damaged one.
from pathlib import Pathfrom tempfile import TemporaryDirectory
import numpy as np
from mtrl import InstrumentRun, MaterialData, Mtrl, forensic_inspect
application = Mtrl(sample_id="polymer-film-01")run = InstrumentRun(run_name="ftir-replicate-01")run.add_checkpoint( MaterialData( content=np.array([0.15, 0.21, 0.19]), type="raw", checkpoint_name="spectrum", ))application.add(run)
with TemporaryDirectory() as directory: archive_path = application.save(Path(directory) / "polymer-film-01.mtrl") result = forensic_inspect(archive_path) print(f"structural status: {result.structural_status.value}; issues: {len(result.issues)}")structural status: valid; issues: 0The print shows structural status: valid; issues: 0: the archive is structurally well
formed and there are no findings. On a damaged archive the same two values carry the
diagnosis — a structural_status of invalid or a digest status of inconsistent, plus
one entry in result.issues per
finding.
What just happened?
Section titled “What just happened?”forensic_inspect(archive_path) read the archive through the same bounded reader that
guards every load, then reported what it could determine safely. The result keeps the
separate verification statuses independent: structural_status (is the archive well
formed), hash_status (do the bytes match their recorded digests), plus anchor_status,
coverage_status, and source_closure_status. There is deliberately no aggregate
verified flag, because a damaged archive can be sound in one layer and broken in
another, and you need to know which.
Each finding in result.issues is one ordered fact, not a verdict. An issue carries a
code naming the failed check, a state such as not-checked, and — where the check
could determine them — the entry_path of the affected archive entry, the digest_layer,
the expected and observed values, and a blocked_by note when one failure prevented a
later check from running. Reading them in order reconstructs what happened to the file.
Notice the boundary the inspection keeps. It reports structural and digest facts and stops there. It does not repair the archive, and it does not make damaged records valid analysis inputs — the purpose is to let you see the damage and decide what to do, not to let the damaged data back into your work.
Caution — Forensic inspection is read-only evidence gathering. Never treat its findings as a repair, and never route a damaged archive back into analysis because the report looked small. If you hold a receipt for the archive, verify the archive against that anchor as well, so you know whether the whole file was replaced.
Where next
Section titled “Where next”- Inside a .mtrl archive — the manifest, the bounded reader, and why each layer is reported separately.
- Anchor verification with receipts — anchor an archive you trust, so a complete replacement is detectable later.
- Reference — exact signatures for
forensic_inspect()and theVerifyResultfields.