# How to Debug Model Loading Failures in ONNX Runtime: Complete Error Handling Guide

> Debug ONNX Runtime model loading failures with its comprehensive error handling. Understand status objects for precise diagnosis of file, protobuf, or session config issues.

- Repository: [Microsoft/onnxruntime](https://github.com/microsoft/onnxruntime)
- Tags: how-to-guide
- Published: 2026-04-24

---

**ONNX Runtime encapsulates every model loading failure in a `common::Status` object that exposes a category, specific error code, and human-readable message, allowing precise diagnosis of whether the failure stems from file system issues, protobuf corruption, or session configuration errors.**

When `InferenceSession::Load` fails in ONNX Runtime, it returns a structured error object rather than throwing exceptions. Understanding how to extract and interpret this diagnostic data is essential for production debugging. This guide examines the `Status` class architecture in [`include/onnxruntime/core/common/status.h`](https://github.com/microsoft/onnxruntime/blob/main/include/onnxruntime/core/common/status.h) and demonstrates how to handle errors across the C++, C, and Python APIs when loading ONNX and ORT format models.

## The Status Class Architecture

All error information in ONNX Runtime lives within the **`common::Status`** class defined in **[`include/onnxruntime/core/common/status.h`](https://github.com/microsoft/onnxruntime/blob/main/include/onnxruntime/core/common/status.h)**. A `Status` instance contains three critical diagnostic fields:

- **Category** – Either `SYSTEM` for OS-level failures or `ONNXRUNTIME` for library-level errors.
- **Code** – An entry from the `StatusCode` enum (lines 34-50) such as `INVALID_ARGUMENT`, `NO_MODEL`, or `MODEL_LOAD_CANCELED`.
- **Message** – A free-form string generated at the failure point explaining the specific context.

The class provides **`IsOK()`** to check success and **`ToString()`** (lines 55-66) to render a human-readable diagnostic formatted as `[Category::ONNXRUNTIME] FAIL: <msg>`. Never ignore the return value of loading operations; always inspect this object before proceeding to `Initialize()`.

## Model Loading Entry Points

The public entry points for model loading are the overloads of **`InferenceSession::Load`** declared in **[`onnxruntime/core/session/inference_session.h`](https://github.com/microsoft/onnxruntime/blob/main/onnxruntime/core/session/inference_session.h)** (lines 94-106). Internally, these delegate to one of three private helpers, each returning a `common::Status`:

- **`LoadOnnxModel(const PathString&)`** – Parses an ONNX file from disk.
- **`LoadOrtModel(const PathString&)`** – Deserializes an ORT-format model.
- **`LoadOrtModel(const void*, int)`** – Loads a model from an in-memory buffer.

Each helper propagates errors from lower layers, such as protobuf parsing failures from [`core/graph/model.h`](https://github.com/microsoft/onnxruntime/blob/main/core/graph/model.h) or file system errors from `Model::Load`.

## Common Model Loading Failure Codes

Mapping the reported `StatusCode` to its source file path accelerates debugging. The following codes frequently appear during `InferenceSession::Load`:

- **`INVALID_ARGUMENT`** – Invalid session options or malformed file paths. Triggered by validation checks inside `Load` before file operations begin.
- **`NO_SUCHFILE`** / **`NO_MODEL`** – The specified file does not exist or cannot be opened, originating in `Model::Load` within [`core/graph/model.h`](https://github.com/microsoft/onnxruntime/blob/main/core/graph/model.h).
- **`MODEL_LOAD_CANCELED`** – The user set `SessionOptions::SetLoadCancellationFlag(true)` before calling `Load`. The session checks `check_load_cancellation_fn_` before proceeding.
- **`INVALID_PROTOBUF`** – The model file is corrupted or uses an incompatible protobuf version, raised during `LoadOnnxModel` parsing.
- **`MODEL_REQUIRES_COMPILATION`** – The model requires ahead-of-time compilation (e.g., for TensorRT), detected in `DoPostLoadProcessing` after graph construction.

Search for `return ORT_MAKE_STATUS` in `onnxruntime/core/session/inference_session.cc` to locate the exact origin of specific error codes.

## Language-Specific Error Handling Patterns

### C++ API: Inspecting the Status Object

In C++, capture the `Status` object returned by `Load` and probe its attributes before converting to a string:

```cpp
#include "onnxruntime/core/session/inference_session.h"
#include "core/common/status.h"

onnxruntime::SessionOptions so;
so.session_log_severity_level = static_cast<int>(onnxruntime::logging::Severity::VERBOSE);
onnxruntime::Environment env(ORT_LOGGING_LEVEL_WARNING, "debug_env");
onnxruntime::InferenceSession session(so, env);

const std::wstring model_path = L"model.onnx";
onnxruntime::common::Status st = session.Load(model_path);

if (!st.IsOK()) {
  LOGS_DEFAULT(ERROR) << "Failed to load model: " << st.ToString();
  
  if (st.Code() == onnxruntime::common::StatusCode::MODEL_LOAD_CANCELED) {
    LOGS_DEFAULT(ERROR) << "Load was cancelled – check SessionOptions::IsLoadCancellationFlagSet()";
  }
  return -1;
}

```

Alternatively, use **`ORT_THROW_IF_ERROR(st)`** to automatically throw an exception containing the `Status` message if the load fails.

### C API: Extracting Messages from OrtStatus

The C API returns errors as an opaque `OrtStatus*` pointer. Always check for `NULL` and retrieve the message using **`OrtGetErrorMessage`**:

```c
OrtEnv* env;
OrtCreateEnv(ORT_LOGGING_LEVEL_WARNING, "debug_c", &env);

OrtSessionOptions* opts;
OrtCreateSessionOptions(&opts);
OrtSetSessionLogSeverityLevel(opts, ORT_LOGGING_LEVEL_VERBOSE);

OrtSession* sess = NULL;
OrtStatus* status = OrtCreateSession(env, "model.onnx", opts, &sess);

if (status != NULL) {
    const char* err = OrtGetErrorMessage(status);
    fprintf(stderr, "ONNX Runtime load error: %s\n", err);
    OrtReleaseStatus(status);
    OrtReleaseSessionOptions(opts);
    OrtReleaseEnv(env);
    return -1;
}

```

Release the status object with **`OrtReleaseStatus`** to prevent memory leaks.

### Python API: Catching RuntimeError

The Python bindings convert C API errors into Python **`RuntimeError`** exceptions. The exception message contains the exact output of `Status::ToString()`:

```python
import onnxruntime as ort

sess_options = ort.SessionOptions()
sess_options.log_severity_level = 0  # VERBOSE

try:
    sess = ort.InferenceSession("model.onnx", sess_options)
except RuntimeError as e:
    print("Model load failed:", e)
    if "MODEL_LOAD_CANCELED" in str(e):
        print("Load was cancelled – verify SessionOptions.set_load_cancellation_flag")

```

The conversion logic resides in `python/onnxruntime_pybind_state.cc`, which calls `OrtGetErrorMessage` under the hood.

## Step-by-Step Debugging Workflow

Follow this systematic approach to diagnose model loading failures:

1. **Enable verbose logging** – Set `session_log_severity_level` to `ORT_LOGGING_LEVEL_VERBOSE` in `SessionOptions` or export `ORT_LOGGING_LEVEL=VERBOSE` to capture the full execution trace.

2. **Capture the Status** – Never ignore return values in C/C++. In Python, wrap the constructor in a try/except block.

3. **Inspect the code** – Map the reported `StatusCode` back to the source by searching for that constant in `onnxruntime/core/session/inference_session.cc`.

4. **Check cancellation flags** – If you encounter `MODEL_LOAD_CANCELED`, verify that `SessionOptions::SetLoadCancellationFlag` was not inadvertently set to `true` before loading.

5. **Validate the model file** – Rule out protobuf corruption by running `onnx.checker.check_model` (Python) or opening the file in Netron to verify node definitions and tensor shapes.

## Summary

- ONNX Runtime reports all model loading failures through the **`common::Status`** class defined in [`include/onnxruntime/core/common/status.h`](https://github.com/microsoft/onnxruntime/blob/main/include/onnxruntime/core/common/status.h).
- The **`InferenceSession::Load`** overloads in [`onnxruntime/core/session/inference_session.h`](https://github.com/microsoft/onnxruntime/blob/main/onnxruntime/core/session/inference_session.h) serve as the primary entry points, delegating to `LoadOnnxModel` or `LoadOrtModel` helpers.
- Key error codes include **`INVALID_PROTOBUF`**, **`NO_MODEL`**, **`INVALID_ARGUMENT`**, and **`MODEL_LOAD_CANCELED`**.
- Extract error details via **`Status::ToString()`** in C++, **`OrtGetErrorMessage`** in C, and **`RuntimeError`** exceptions in Python.
- Always enable verbose logging and validate model files independently to distinguish between runtime configuration issues and corrupted model data.

## Frequently Asked Questions

### What is the difference between SYSTEM and ONNXRUNTIME status categories?

The **SYSTEM** category indicates OS-level failures, such as file permission errors or out-of-memory conditions returned by the operating system. The **ONNXRUNTIME** category indicates library-level logic errors, such as invalid protobuf formats, unsupported ops, or configuration mistakes detected by ONNX Runtime's internal validation layers. Both categories use the same `StatusCode` enumeration but require different remediation strategies.

### How do I detect if a load was cancelled versus failed due to file corruption?

Check the **`StatusCode`** enum value returned by `st.Code()` or scan the error message string for `MODEL_LOAD_CANCELED`. This specific code indicates that the load operation was interrupted because `SessionOptions::SetLoadCancellationFlag(true)` was called before or during the load. File corruption, by contrast, produces **`INVALID_PROTOBUF`** or **`NO_MODEL`** codes.

### Why does Python raise RuntimeError instead of a specific exception class?

The Python bindings in `onnxruntime_pybind_state.cc` convert the underlying C `OrtStatus*` into a **`RuntimeError`** to maintain compatibility across versions and simplify the binding layer. The exception message preserves the full diagnostic detail from `Status::ToString()`, including the error code and human-readable description, allowing you to programmatically inspect the specific failure type by parsing the message string.

### Where does the INVALID_PROTOBUF error originate in the codebase?

The **`INVALID_PROTOBUF`** code originates in **[`onnxruntime/core/graph/model.h`](https://github.com/microsoft/onnxruntime/blob/main/onnxruntime/core/graph/model.h)** and **`model.cc`** during the call to `Model::Load`. When `InferenceSession::LoadOnnxModel` invokes the protobuf parser, any corruption, version mismatch, or truncation detected in the ONNX file triggers this status. You can validate the file independently using the `onnx` Python package or Netron before attempting runtime loading.