Extensible and beautiful ONNX checker
Project description
ONNX Doctor
An extensible linter for ONNX models — like ruff, but for ONNX. Catch spec violations, compatibility issues, and common pitfalls with clear messages and actionable suggestions.
Installation
pip install onnx-doctor
Quick Start
CLI
Check a model for issues:
onnx-doctor check model.onnx
Example output:
model.onnx:graph: ONNX001 Graph name is empty.
suggestion: Set the name of the graph, e.g. `graph.name = 'main_graph'`.
model.onnx:graph:node/5(MyCustomOp): ONNX019 No schema found for '::MyCustomOp' at opset version 21.
suggestion: Verify the operator name, domain, and imported opset version.
model.onnx:graph:node/5(MyCustomOp): ONNX020 Value 'custom_out' has no type annotation.
suggestion: Run shape inference on the model, e.g. `onnx.shape_inference.infer_shapes(model)`.
Found 2 errors, 1 warning.
The location path shows where the issue is in the graph hierarchy. For nodes,
it includes the node index and name (e.g. node/5(MyCustomOp)). For values,
it shows the producer node. For subgraphs, the full path is shown:
model.onnx:graph:node/3(If_0):then_branch:node/1(Add): ONNX019 ...
Programmatic API
import onnx_ir as ir
import onnx_doctor
from onnx_doctor.diagnostics_providers import OnnxSpecProvider
model = ir.load("model.onnx")
messages = onnx_doctor.diagnose(model, [OnnxSpecProvider()])
for msg in messages:
print(f"[{msg.severity}] {msg.error_code}: {msg.message}")
CLI Reference
onnx-doctor <command> [options]
check — Lint an ONNX model
onnx-doctor check model.onnx [options]
| Option | Description |
|---|---|
--select CODE [...] |
Only report rules matching these codes or prefixes (e.g. ONNX001, ONNX). |
--ignore CODE [...] |
Ignore rules matching these codes or prefixes. |
--output-format {text,json,github} |
Output format. Default: text. |
--severity {error,warning,info} |
Minimum severity to report. |
--fix |
Apply available fixes and save the model. |
-o, --output PATH |
Output path for the fixed model (default: overwrite input). Only used with --fix. |
--diff |
Show a unified diff of what --fix would change, without writing. |
--ort |
Enable ONNX Runtime compatibility checks (ORT rules). |
--ort-provider NAME |
Execution provider for ORT checks (default: CPUExecutionProvider). |
Exit codes: 0 = no errors (warnings may be present), 1 = errors found.
Examples:
# Ignore ir-version warnings
onnx-doctor check model.onnx --ignore ONNX013
# Only show errors
onnx-doctor check model.onnx --severity error
# Apply auto-fixes in place
onnx-doctor check model.onnx --fix
# Apply auto-fixes to a new file
onnx-doctor check model.onnx --fix -o fixed_model.onnx
# Preview what --fix would change
onnx-doctor check model.onnx --diff
# Enable ORT compatibility checks
onnx-doctor check model.onnx --ort
# JSON output for CI
onnx-doctor check model.onnx --output-format json
# GitHub Actions annotations
onnx-doctor check model.onnx --output-format github
JSON output example:
[
{
"file": "model.onnx",
"code": "ONNX001",
"severity": "error",
"message": "Graph name of the root graph is empty.",
"target_type": "graph",
"location": "graph",
"rule_name": "empty-graph-name",
"suggestion": "Set the name of the graph, e.g. `graph.name = 'main_graph'`."
}
]
explain — Show rule details
onnx-doctor explain ONNX001
ONNX001: empty-graph-name
Message: Graph name of the root graph is empty.
Severity: error
Category: spec
Target: graph
Suggestion: Set the name of the graph, e.g. `graph.name = 'main_graph'`.
## Details
The 'name' field of a graph must not be empty per the ONNX spec.
You can also look up rules by name:
onnx-doctor explain empty-graph-name
list-rules — Show all available rules
onnx-doctor list-rules
Rules
ONNX Doctor ships with 63 built-in rules across five providers:
| Prefix | Provider | Description |
|---|---|---|
ONNX |
ONNX Spec | 42 rules for ONNX spec compliance (graph, model, node, value, tensor, function) |
PB |
Protobuf | 13 rules for protobuf-specific issues |
SIM |
Simplification | 3 rules for removing unused elements (functions, opsets, nodes) |
ORT |
ORT Compatibility | 5 rules for ONNX Runtime compatibility checks (opt-in via --ort) |
SP |
Sparsity | Tensor sparsity analysis (example provider, not enabled by default) |
Writing Custom Providers
Create your own rules by subclassing DiagnosticsProvider. Each provider
implements a diagnose(model) method that walks the model and yields messages:
import onnx_ir as ir
import onnx_doctor
class MyProvider(onnx_doctor.DiagnosticsProvider):
def diagnose(self, model: ir.Model):
# Walk the graph yourself — you know best how to traverse it
for node in ir.traversal.RecursiveGraphIterator(model.graph):
if some_condition(node):
yield onnx_doctor.DiagnosticsMessage(
target_type="node",
target=node,
message=f"Issue with node {node.op_type}.",
severity="warning",
producer="MyProvider",
error_code="CUSTOM001",
)
# Check graph-level properties
node_count = sum(1 for _ in model.graph)
if node_count > 1000:
yield onnx_doctor.DiagnosticsMessage(
target_type="graph",
target=model.graph,
message=f"Graph has {node_count} nodes — consider optimizing.",
severity="warning",
producer="MyProvider",
error_code="CUSTOM002",
)
model = ir.load("model.onnx")
messages = onnx_doctor.diagnose(model, [MyProvider()])
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file onnx_doctor-0.2.0.tar.gz.
File metadata
- Download URL: onnx_doctor-0.2.0.tar.gz
- Upload date:
- Size: 54.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa3b01d49b1509d17decda14a22f57186790504bdbf442aaa87eab8bddba1b57
|
|
| MD5 |
d3f1799b8c4af207728f20d7167aa564
|
|
| BLAKE2b-256 |
cb6273deb39b95db2afb5e2bf28fc261b78e461613edd1ae7242d395d625e2ef
|
Provenance
The following attestation bundles were made for onnx_doctor-0.2.0.tar.gz:
Publisher:
main.yml on justinchuby/onnx-doctor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
onnx_doctor-0.2.0.tar.gz -
Subject digest:
fa3b01d49b1509d17decda14a22f57186790504bdbf442aaa87eab8bddba1b57 - Sigstore transparency entry: 953227509
- Sigstore integration time:
-
Permalink:
justinchuby/onnx-doctor@3aacb43677d561f7df346cca0bac9593c9fe8f5d -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/justinchuby
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
main.yml@3aacb43677d561f7df346cca0bac9593c9fe8f5d -
Trigger Event:
push
-
Statement type:
File details
Details for the file onnx_doctor-0.2.0-py3-none-any.whl.
File metadata
- Download URL: onnx_doctor-0.2.0-py3-none-any.whl
- Upload date:
- Size: 62.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cc00bb36d2feb5de126d9d7f7278b85a21eb827ce350cb3952bffe93a914cd41
|
|
| MD5 |
95f630e677bfabe7bd615d88449219a8
|
|
| BLAKE2b-256 |
7a6d75064d4364b37c801fae48a75c83a999ee75e245e115807b4b7ec6e6a96f
|
Provenance
The following attestation bundles were made for onnx_doctor-0.2.0-py3-none-any.whl:
Publisher:
main.yml on justinchuby/onnx-doctor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
onnx_doctor-0.2.0-py3-none-any.whl -
Subject digest:
cc00bb36d2feb5de126d9d7f7278b85a21eb827ce350cb3952bffe93a914cd41 - Sigstore transparency entry: 953227512
- Sigstore integration time:
-
Permalink:
justinchuby/onnx-doctor@3aacb43677d561f7df346cca0bac9593c9fe8f5d -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/justinchuby
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
main.yml@3aacb43677d561f7df346cca0bac9593c9fe8f5d -
Trigger Event:
push
-
Statement type: