Experimental. Not tested on production data. Feedback welcome.
A VEP-annotated VCF describes itself in several places — ##reference,
##VEP, ##contig headers, CSQ field declarations — and those descriptions
can contradict each other. vep-preflight reads the file, compares what the
headers say, and reports internal inconsistencies before downstream tools
trip over them.
It does not validate biology. It does not check whether annotations are correct. It checks whether a file agrees with itself.
vep-preflight file.vcf # check a file
cat file.vcf | vep-preflight # read from stdin (auto-detected)
vep-preflight - < file.vcf # read from stdin (explicit)
vep-preflight --format json file.vcf # JSON output on stdout
vep-preflight -W file.vcf # treat warnings as errors
vep-preflight --list-checks # show all available checks
Findings go to stdout, status/progress to stderr.
Exit codes: 0 clean, 1 errors found, 2 bad usage.
31 checks across 7 groups. Run --list-checks for the full table.
| Group | Codes | What it catches |
|---|---|---|
| Genome build | E004 E005 E007 W005 I001 I010–I012 | ##reference says GRCh37 but ##VEP says GRCh38, contig lengths don't match the claimed build, etc. |
| CSQ structure | E001 E002 E006 W008 I002 I005–I007 | Missing or duplicate CSQ header, wrong number of pipe-delimited fields, declared fields that are always empty |
| VEP source info | W001–W004 | No ##VEP header, VEP version doesn't match cache version |
| Chromosome naming | W006 W007 | Headers use chr1 but data uses 1, or a mix of both |
| Multi-allelic | W009 W010 I008 I009 | Can't tell which CSQ entry belongs to which ALT allele |
| Annotation tags | I003 I004 | File has BCSQ (bcftools) where CSQ (VEP) was expected, or both |
| Parsing | E003 E010 E011 | noodles rejects the header or individual records |
Each check is documented in its source module under src/checks/, with links
to the upstream issue where real users hit the problem.
Any check's severity can be changed at runtime, or suppressed entirely:
vep-preflight --severity W001=error --severity I005=off file.vcf
Valid levels: error, warning, info, off.
Place a .vep-preflight.toml in your project directory (searched upward from
cwd). CLI flags override config values.
[severity]
W001 = "off" # suppress "no VEP header" in this project
I005 = "warning" # promote missing CSQ records to warning
[defaults]
warnings-as-errors = true
format = "text" # or "json"From source (requires Rust):
cargo install --git https://github.com/werner291/vep-preflight
With Nix (run without installing):
nix run github:werner291/vep-preflight -- file.vcf
With Nix (permanent install via nix profile):
nix profile install github:werner291/vep-preflight
Or add to your NixOS/home-manager configuration as a flake input:
# flake.nix
inputs.vep-preflight.url = "github:werner291/vep-preflight";
# configuration.nix or home.nix
environment.systemPackages = [ inputs.vep-preflight.packages.${system}.default ];
# or
home.packages = [ inputs.vep-preflight.packages.${system}.default ];- Loads the entire VCF into memory. Not suitable for multi-GB whole-genome VCFs. Works fine for exome and targeted panel VCFs.
- The checks come from reading upstream issue trackers (pVACtools, VAtools, Ensembl VEP, vcf2maf), not from running these tools directly. If you find a false positive or a missed case, please open an issue.
Not affiliated with Ensembl, EMBL-EBI, or any upstream project whose issues or test data are referenced in the source.
Development assisted by Claude (Anthropic). The checks are derived from real failure modes documented in upstream issue trackers. Evidence links in the source point to those discussions.
Apache-2.0. See LICENSE.
If you use this in your work, a citation is appreciated — see CITATION.cff.