microsoft / microsoft/onnxruntime
[Bug] ReshapeFusion: fused Reshape used as shape input → type error (tensor(float) vs tensor(int64))
- Dominant language
- C++
- Stars
- 21.9k
- Forks
- 4.2k
- Avg merge
- 4d 11h
- Merged PRs (30d)
- 184
Description
**Describe the bug**
On opset 21, when a `Reshape` node's output is consumed as the *shape input* of a downstream `Reshape` (rather than as data), the `ReshapeFusion` graph optimizer incorrectly fuses the two Reshape nodes. The fused node (`_new_reshape`) ends up with an output type of `tensor(float)` while the graph declares/expects `tensor(int64)`, so `InferenceSession` creation raises a hard type error. The bug triggers at the **default** optimization level — it fails even at `ORT_ENABLE_BASIC` (level 1); with `ORT_DISABLE_ALL` the same model runs correctly and produces `Y = [10, 20, 30, 40]`.
**Urgency**
none
**System information**
- OS Platform and Distribution (e.g., Linux Ubuntu 16.04): Linux Ubuntu 20.04.4 LTS (x86_64), kernel 5.15.0-70-generic
- ONNX Runtime installed from (source or binary): binary (pip, CPU package)
- ONNX Runtime version: 1.28.0
- Python version: 3.11.7
- Visual Studio version (if applicable): n/a
- GCC/Compiler version (if compiling from source): n/a
- CUDA/cuDNN version: n/a (CPU only)
- GPU model and memory: n/a
- PyTorch version: n/a
- ONNX version: 1.22.0
- numpy version: 1.26.4
**To Reproduce**
- Describe steps/code to reproduce the behavior.
```python
import numpy as np
import onnx
from onnx import helper, TensorProto, numpy_helper
import onnxruntime as ort
# Build the minimal model (3 nodes):
# A (float[1,1]) --Cast(to=int64)--> A_int (int64[1,1])
# A_int --Reshape(shape=[1])--> R (int64[1]) # no-op reshape
# Data (float[4]) --Reshape(shape=R)--> Y (float[4])
A = helper.make_tensor_value_info("A", TensorProto.FLOAT, [1, 1])
Y = helper.make_tensor_value_info("Y", TensorProto.FLOAT, [4])
nodes = [
helper.make_node("Cast", ["A"], ["A_int"], to=TensorProto.INT64),
helper.make_node("Reshape", ["A_int", "shape"], ["R"]),
helper.make_node("Reshape", ["Data", "R"], ["Y"]),
]
initializers = [
numpy_helper.from_array(np.array([1], dtype=np.int64), "shape"),
numpy_helper.from_array(np.array([10.0, 20.0, 30.0, 40.0], dtype=np.float32), "Data"),
]
graph = helper.make_graph(nodes, "minimal_reshape_fusion", [A], [Y], initializers)
model = helper.make_model(graph, opset_imports=[helper.make_opsetid("", 21)])
model.ir_version = 6
feed = {"A": np.array([[4.0]], dtype=np.float32)}
# 1) Optimizations disabled -> works, prints [10. 20. 30. 40.]
so_off = ort.SessionOptions()
so_off.graph_optimization_level = ort.GraphOptimizationLevel.ORT_DISABLE_ALL
sess_off = ort.InferenceSession(model.SerializeToString(), so_off, providers=["CPUExecutionProvider"])
print(sess_off.run(None, feed)[0])
# 2) Default optimizations -> crashes at session creation
so_on = ort.SessionOptions()
so_on.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
sess_on = ort.InferenceSession(model.SerializeToString(), so_on, providers=["CPUExecutionProvider"]) # 💥
```
- Attach the ONNX model to the issue (where applicable) to expedite investigation.
Attached file: minimal_reshape_fusion_bug.onnx.zip
Plain text proto:
```proto
ir_version: 6
graph {
node {
input: "A"
output: "A_int"
op_type: "Cast"
attribute {
name: "to"
i: 7
type: INT
}
}
node {
input: "A_int"
input: "shape"
output: "R"
op_type: "Reshape"
}
node {
input: "Data"
input: "R"
output: "Y"
op_type: "Reshape"
}
name: "minimal_reshape_fusion"
initializer {
dims: 1
data_type: 7
name: "shape"
raw_data: "\001\000\000\000\000\000\000\000"
}
initializer {
dims: 4
data_type: 1
name: "Data"
raw_data: "\000\000 A\000\000\240A\000\000\360A\000\000 B"
}
input {
name: "A"
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_value: 1
}
dim {
dim_value: 1
}
}
}
}
}
output {
name: "Y"
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_value: 4
}
}
}
}
}
}
opset_import {
domain: ""
version: 21
}
```
**Expected behavior**
Should not crash under default optimizations; `InferenceSession` should be created successfully and produce `Y = [10, 20, 30, 40]`, but instead raises: `[ONNXRuntimeError] : 1 : FAIL : Type Error: Type (tensor(float)) of output arg (Y) of node (_new_reshape) does not match expected type (tensor(int64)).`
**Screenshots**
n/a
[minimal_reshape_fusion_bug.onnx.zip](https://github.com/user-attachments/files/31093605/minimal_reshape_fusion_bug.onnx.zip)
Contributor guide
Research direction
Start by running the provided Python reproducer with the attached minimal_reshape_fusion_bug.onnx model at disabled and basic/default optimization levels. Trace the ReshapeFusion entry point and the fused _new_reshape output types, then verify that InferenceSession creation succeeds and produces Y = [10, 20, 30, 40] without optimization-related type errors.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- machine-learning
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100