## TL;DR
nmap writes the XML file only when the scan finishes, so a crash leaves it truncated or empty. Check whether the normal (-oN) or grepable (-oG) output survived, salvage what you can from it, then re-run the scan in smaller chunks with a separate output file per chunk so one crash cannot take the whole run.

```text
nmap: XML output file truncated / empty after scan aborted
```

## Use this when
- The -oX file is empty, truncated, or fails to parse after a crash.
- You still need results for the authorized scope.
- The crash killed nmap itself (OOM, box reboot, killed process).

## Not for this skill when
- The XML parses fine. A parsing complaint from your own script is a different bug.
- The scan finished. Then the output is complete by definition.

## Steps
1. Check what actually survived: `ls -la scan.*` and `tail -5 scan.nmap`. The normal output file is written incrementally and often has partial results. Verify: you know which output files have usable data.
2. Salvage host and port lines from the normal output: `grep -E "Nmap scan report|open" scan.nmap`. Verify: you recover the hosts that completed before the crash.
3. Re-run in chunks so a repeat crash costs minutes, not hours: `nmap -sS -oA chunk1 192.0.2.0/25`. Verify: each chunk writes its own .nmap, .xml, and .gnmap on completion.
4. Merge chunk XML only from files that parse: `python3 -c "import xml.dom.minidom; xml.dom.minidom.parse('chunk1.xml')"`. Verify: every merged file is well-formed before you combine them.
5. Find the crash cause before the next big run: check `dmesg | grep -i oom` for out-of-memory kills, the usual suspect on small test VMs. Verify: you fixed the cause, not just the symptom.

Compatibility: nmap 7.x. -oA behavior is unchanged across recent versions.

## Variant phrasings
### nmap xml output empty after crash
Same fix path, common phrasing.
### nmap scan crashed no xml results
Symptom-level search.
### recover nmap partial results crashed scan
The salvage-oriented search.

## Why it happens
nmap buffers the XML document in memory and writes it at the end of the run, while the normal text output streams to disk as hosts complete. A crash between those two moments leaves a truncated XML file and a usable text file. This is by design for XML validity: a half-written XML file would be worse than none.

## Edge cases / pitfalls
- -oG grepable output is also incremental and easy to re-parse. Prefer it for chunked runs your scripts consume.
- The .gnmap file may claim a host "up" that never got its ports scanned. Cross-check with the .nmap text.
- If OOM is the cause, reduce parallelism with --max-parallelism rather than just re-running.
- Log the crash and the salvage in your report methodology. Partial coverage is a finding about the engagement, not just your tooling.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_kjzOKxSlaQLE8UIfKCviAg
