Skip to main content

trtcheck: static pre-flight checks for ONNX to TensorRT conversion

ci pypi python license

trtcheck is a static analysis tool for the ONNX → TensorRT conversion step. It reads an ONNX file, runs five independent checkers against a per-version TensorRT operator matrix, and reports whether the model will convert — with a specific remediation for each blocker it finds. Five built-in fixers rewrite the common failure patterns. Analysis runs in seconds and needs no TensorRT install, CUDA, or GPU, so it works on a laptop and in CI.

trtcheck demo: the UINT8 case before and after --fix

Install

pip install trtcheck

Or from source for development:

git clone https://github.com/sohams25/trtcheck.git
cd trtcheck
pip install -e ".[dev]"

Python 3.10–3.13, onnx >= 1.15, < 2.0. No platform dependencies beyond onnx itself — analysis needs no TensorRT, no GPU. Modeled TensorRT targets: 8.0, 8.6, 10.0, 10.3; each operator entry carries its own evidence level (official documentation, inferred, or unknown — see docs/rules.md and the operator pages).

Quick start

$ trtcheck model.onnx
CONVERSION BLOCKED — 1 critical, 0 warning
CRITICAL  input  Input  Input 'input' has dtype UINT8; TensorRT
                        accepts only FP32, FP16, INT32, or INT8
                        as graph inputs.
                        → Move the UINT8 → FLOAT32 conversion (and
                          normalization) into your preprocessing
                          pipeline rather than the model body.

Estimated fix time: 15–30 minutes.

Every report carries one of four verdicts — blocked (a known critical incompatibility), unverified (no known blocker, but unresolved conditions: unclassified or custom-domain operators, conditional support that static analysis cannot settle), likely (all static checks passed — a prediction, not a guarantee), and verified (an optional real trtexec build succeeded via --verify-runtime). The exit code is 1 on blocked and 0 otherwise (--fail-on unverified tightens the CI gate), so the same command works unchanged as a CI gate. docs/case-studies/uint8-input.md walks this exact case end to end, including the --fix rewrite that turns it into a passing graph. Verdict accuracy is measured: SCORECARD.md publishes precision and recall against a corpus with known conversion outcomes.

Motivation

trtexec reports conversion problems at engine build time, one at a time, as C++ log output. Some common failures and what they trace back to:

trtexec error Actually means Root cause
UNSUPPORTED_NODE: SequenceEmpty Your model contains an ONNX sequence op PyTorch List[Tensor] = [] in forward()
Assertion failed: convert_dtype: UINT8 Graph input dtype is uint8 Image preprocessing with np.uint8
at least 5 dimensions are required MaxPool sees a tensor that lost rank after shape inference Dynamic batch combined with reshape
INT64 weights detected … not natively supported A Constant or Initializer is int64 torch.LongTensor for argmax / indices
Network must have at least one output Shape inference removed every output If / Loop with dynamic shape

trtcheck runs the equivalent compatibility checks statically, so every issue in the model surfaces in one pass, as a named finding with a fix, before an engine build is attempted.

What it checks

Checker Catches
operator support Ops missing or partial in the target TRT version (e.g. SequenceEmpty, GroupNormalization on TRT 8.x); documented conditional-support rules (e.g. TopK sorted=0, cubic Resize); honest unverified findings for operators the matrix does not classify and for custom-domain ops that need a TRT plugin
precision UINT8 / INT64 / FLOAT64 / STRING / BFLOAT16 graph inputs, INT64 weights, and FLOAT64 introduced by a Cast or Constant anywhere in the graph
dynamic shapes Two or more symbolic input dims, including dynamic dims encoded as a concrete -1
control flow Loop with runtime trip count, nested Loop, If, Scan
graph structure Empty outputs, duplicate node names, oversized constants

Every check descends into If / Loop / Scan subgraph bodies — an unsupported op buried in a branch is caught, not waved through. Each finding includes a specific remediation. Not "this is bad" — what to change, where.

What it auto-fixes

--fix runs an audited, transactional pipeline: every fixer works on an isolated candidate copy, the result must pass full ONNX validation (strict type/shape inference) before it is kept, and the report shows which findings were resolved, which remain, and whether any were introduced. A fixer that crashes — including a third-party plugin — cannot leave a half-rewritten model. Use --dry-run to preview.

Fixer Rewrites
uint8_input Promotes a UINT8 graph input to FLOAT and drops the redundant downstream Cast
int64_to_int32 Casts INT64 initializers to INT32 only when every use is at a schema position that accepts INT32 (e.g. Gather indices) — never Reshape/Slice shape inputs, which require INT64
float64_to_float32 Casts FLOAT64 initializers to FLOAT32 when no value is NaN, infinite, or out of FP32 range
drop_dropout Removes Dropout nodes that are provably in inference mode (training_mode absent or statically false; mask unused)
upsample_to_resize Rewrites leftover deprecated Upsample nodes as Resize on opset-13+ graphs (nearest / linear)
trtcheck model.onnx --fix --dry-run                    # preview
trtcheck model.onnx --fix --output fixed.onnx          # apply

Refuses to overwrite the input or an existing output unless you pass --force.

Measured accuracy

The bench/ harness scores trtcheck's verdicts against a corpus with known conversion outcomes. Latest run against the TRT 10.3 matrix:

Corpus Blocker precision Blocker recall Unverified coverage Total wall time
12 models: 3 from the ONNX Model Zoo, 9 bundled fixtures 1.000 1.000 0.250 2.3 s

unverified predictions are never counted as successes — they are reported separately, split by ground truth. Twelve models is a small corpus and the failure cases are synthetic, so read this as "the checks do what they claim on known patterns", not as a field-accuracy estimate. For the scorecard corpus, ground truth is documented TRT behavior, not a live trtexec run. Separately, the runtime-verification integration was smoke-tested against real TensorRT 10.3.0 (official NGC container, 7 representative fixtures: 5 genuine engine builds, 2 genuine parser failures, full agreement between --verify-runtime and direct trtexec) — see REAL_TENSORRT_VALIDATION_REPORT.md. That validates the integration path and those cases, not universal model compatibility. SCORECARD.md has the per-model table, the methodology, and what each run caught (the first run's false negative became the loop_runtime_trip_count critical check; this run exposed a Clip coverage gap in the matrix). To grow the corpus, add a model with a known outcome to bench/manifest.yaml and open a PR.

How it compares

trtcheck Polygraphy Netron
Needs TensorRT / GPU no yes, for conversion checks no
Time to a verdict seconds minutes (builds a real engine) manual inspection
Fix suggestions per-finding remediation + --fix rewrites no no
CI integration exit code, JSON, GitHub Action scriptable, needs a GPU runner no
Verdict strength predicts the build outcome (and says so: four-state verdict with explicit uncertainty; optional --verify-runtime runs trtexec when available) proves it n/a

Use them together. Polygraphy building an engine is the ground truth; if you have the GPU and the minutes, run it. Netron is for eyeballing a graph once you know which node to look at. trtcheck is the ten-second gate that runs before either: on a laptop, in CI, on every PR.

Usage

# basic check (defaults to TensorRT 10.3)
trtcheck model.onnx

# target a specific TensorRT version
trtcheck model.onnx --target-trt 8.6

# machine-readable output for CI
trtcheck model.onnx --format json --output report.json

# self-contained HTML report
trtcheck model.onnx --format html --output report.html

# filter to blockers only
trtcheck model.onnx --severity critical

# compare two versions of a model (before / after a fix)
trtcheck before.onnx after.onnx --diff

# auto-fix simple issues (transactional; reports resolved/remaining findings)
trtcheck model.onnx --fix --output model_fixed.onnx

# strict CI gate: also fail on unresolved conditions
trtcheck model.onnx --fail-on unverified

# optional: verify with a real TensorRT build (needs trtexec)
trtcheck model.onnx --verify-runtime

Exit code is 1 on a blocked verdict, 0 otherwise; --fail-on unverified also fails on unresolved conditions. Findings carry stable rule ids (TRT-OP-UNSUPPORTED, TRT-DTYPE-UINT8-INPUT, ...) for CI filtering — see docs/rules.md and docs/usage.md.

Full CLI reference: trtcheck --help.

Use it as a GitHub Action

Ships a composite Action that runs on PRs touching *.onnx files and posts a sticky comment summarizing the report. The dual-workflow pattern (analyze on PR head with read-only token, comment from base repo with write token) keeps fork PRs safe.

.github/workflows/trtcheck.yml:

name: trtcheck
on:
  pull_request:
    paths: ["**/*.onnx"]
permissions:
  contents: read
jobs:
  analyze:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }
      - id: trtcheck
        uses: sohams25/trtcheck@v1
        with:
          target-trt: "10.3"
          fail-on: "critical"
      - if: always()
        run: |
          mkdir -p comment-artifact
          cp "${{ steps.trtcheck.outputs.comment-md }}" comment-artifact/body.md
          echo "${{ github.event.pull_request.number }}" > comment-artifact/pr-number.txt
      - if: always()
        uses: actions/upload-artifact@v4
        with: { name: trtcheck-comment, path: comment-artifact/ }

Pair with trtcheck-comment.yml to post the comment from the base repo. Full template at .github/workflows/example-consumer/trtcheck-comment.yml.

Action inputs

Input Default Purpose
version 1.1.0 trtcheck PyPI version to install
target-trt 10.3 --target-trt value
severity warning --severity filter
fail-on critical Exit policy: critical, warning, or never
paths **/*.onnx Glob of files to consider
changed-only true Only analyze PR-changed files
base-ref (PR base sha) Base ref to diff against when changed-only is set
source-path (unset) Install trtcheck from a local path instead of PyPI; used by the selftest workflow

Action outputs

report-json, comment-md, critical-count, warning-count, status (pass / fail).

Plugins

Third-party packages can ship checkers, fixers, and reporters via Python entry-points:

[project.entry-points."trtcheck.fixers"]
strip_identity = "your_package.fixers:StripIdentityFixer"

The Protocols live in trtcheck.plugins. Worked example at examples/trtcheck-extra-fixers/. Confirm a plugin loaded with trtcheck --list-plugins; filter one out without uninstalling with trtcheck --disable-plugin NAME.

Full surface at docs/design/plugin-sdk.md. The public extension API was frozen at v1.0 and follows semver from here.

The operator matrix

trtcheck/data/operator_matrix.json is a hand-curated mapping from ONNX operators to their support status across TRT 8.0, 8.6, 10.0, and 10.3. Refresh recipe:

# edit the generator
$EDITOR tools/build_operator_matrix.py

# regenerate the JSON
python tools/build_operator_matrix.py

# validate
pytest tests/test_data_files.py -v

# detect drift against the upstream onnx-tensorrt operators table
python tools/check_matrix_drift.py

Run the drift check before each release to keep the matrix honest.

Contributing

python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

./scripts/run-tests.sh        # full pytest suite
mypy trtcheck/                # strict type check
black . && isort .            # format

TDD is mandatory for new checkers, fixers, and reporters. The full contribution guide — TDD cycle, operator-matrix refresh recipe, plugin authoring layout — lives in CONTRIBUTING.md. Security disclosures: SECURITY.md.

Roadmap

  • Grow the bench corpus past nine models with real-world failing models (detection heads, transformer blocks) and publish a refreshed SCORECARD.md per release.
  • Run the trtexec leg of the harness on GPU hardware and reconcile the manifest's expected outcomes against live TRT behavior.
  • Track new TensorRT releases in the operator matrix. The weekly matrix-drift Action already files a tracking issue when the upstream operator table moves.

Shipped: the validation scorecard and the scheduled matrix-drift Action. See CHANGELOG.md for release notes.

Citation

If trtcheck saves your project some GPU hours, a citation is welcome:

@misc{trtcheck,
  title  = {trtcheck: a static pre-flight checker for ONNX to TensorRT conversion},
  author = {Soham},
  year   = {2026},
  url    = {https://github.com/sohams25/trtcheck}
}

Using it in CI? Open a PR adding your project to this section.

License

MIT. See LICENSE.

Metadata

Release files for trtcheck 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for trtcheck 1.1.0
File Size Uploaded Provenance Actions
trtcheck-1.1.0.tar.gz 122.3 kB With provenance Details for trtcheck-1.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for trtcheck 1.1.0
File Interpreter ABI Platform Actions
trtcheck-1.1.0-py3-none-any.whl Python 3 none any Details for trtcheck-1.1.0-py3-none-any.whl

Total release size: 193.0 kB

Release files / trtcheck-1.1.0.tar.gz

Download URL trtcheck-1.1.0.tar.gz
Size 122.3 kB
Tags Source
SHA-256 checksum
How to use checksums
7096de6d9f16652ff495623ca9fbe9019bb663617cac51b5a649c93dc63fccf0
BLAKE2b-256 checksum
How to use checksums
d9c1be93019da940a7f231320dba69a7ce2e45bd8d51bb215f6f3655d94e3647
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 22, 2026.

Transparency log

Release files / trtcheck-1.1.0-py3-none-any.whl

Download URL trtcheck-1.1.0-py3-none-any.whl
Size 70.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1611441fd35d5bd48464ea38a9909b32893b2a452c84b470e9b8ac35a51fe9da
BLAKE2b-256 checksum
How to use checksums
b487c355c4cc0831a608129d73a596d1a2983e009a34a7d0d3a24a2cfe6914a0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 22, 2026.

Transparency log

Security for trtcheck 1.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for trtcheck-1.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 22, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page