Skip to content

Fix CustomOp forward compatibility: cap version instead of rejecting#29574

Merged
chilo-ms merged 5 commits into
mainfrom
chilo-ms/fix-customop-forward-compat
Jul 7, 2026
Merged

Fix CustomOp forward compatibility: cap version instead of rejecting#29574
chilo-ms merged 5 commits into
mainfrom
chilo-ms/fix-customop-forward-compat

Conversation

@chilo-ms

@chilo-ms chilo-ms commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Description

Remove the blanket version check in CustomOpKernel that prevented custom ops compiled against a newer ORT from loading on an older runtime. Instead, cap the version passed to GetApi() at ORT_API_VERSION.

This aligns custom ops with the EP plugin ABI pattern where forward compatibility is supported via runtime version detection. Individual newer functions in OrtCustomOp (CreateKernelV2, InferOutputShapeFn, GetMayInplace, etc.) are already gated by per-function version checks throughout custom_ops.cc, making the blanket reject both redundant and harmful.

The EP is responsible for not calling API functions newer than the runtime version -- the same contract as the EP plugin interface.

Motivation and Context

chilo-ms and others added 3 commits July 6, 2026 09:46
Remove the blanket version check in CustomOpKernel that prevented custom
ops compiled against a newer ORT from loading on an older runtime. Instead,
cap the version passed to GetApi() at ORT_API_VERSION.

This aligns custom ops with the EP plugin ABI pattern where forward
compatibility is supported via runtime version detection. Individual newer
functions in OrtCustomOp (CreateKernelV2, InferOutputShapeFn, GetMayInplace,
etc.) are already gated by per-function version checks throughout
custom_ops.cc, making the blanket reject both redundant and harmful.

The EP is responsible for not calling API functions newer than the runtime
version -- the same contract as the EP plugin interface.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Test that a custom op with OrtCustomOp::version > ORT_API_VERSION can be
registered and executed. This simulates the forward compatibility scenario
where an IHV EP compiled against a newer ORT is loaded into an older runtime.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The MyCustomKernel::Compute tries to get an arena allocator which may not
be available in all CI configurations. Since the fix being tested is in
CustomOpKernel construction (version capping), session creation is sufficient
to exercise the relevant code path.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts custom-op loading behavior to improve forward compatibility: instead of rejecting custom ops whose OrtCustomOp::version is higher than the runtime’s ORT_API_VERSION, the runtime now caps the version used when selecting the OrtApi* passed into custom-op callbacks.

Changes:

  • Update CustomOpKernel construction to use GetApi(min(op.version, ORT_API_VERSION)) rather than rejecting newer versions.
  • Add a C API test that simulates a “newer-compiled” custom op by setting custom_op.version = ORT_API_VERSION + 1 and verifying session creation succeeds.
  • Update OrtCustomOp::version header comment to document the capping behavior.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
onnxruntime/core/session/custom_ops.cc Caps the API version used for OrtGetApiBase()->GetApi(...) during custom kernel creation to enable forward compatibility.
onnxruntime/test/shared_lib/test_inference.cc Adds a regression test covering forward-compat custom-op loading (session creation path).
include/onnxruntime/core/session/onnxruntime_c_api.h Updates the OrtCustomOp::version documentation to reflect new runtime behavior.

Comment thread onnxruntime/core/session/custom_ops.cc
Comment thread onnxruntime/core/session/custom_ops.cc Outdated
Comment thread onnxruntime/test/shared_lib/test_inference.cc
Comment thread include/onnxruntime/core/session/onnxruntime_c_api.h Outdated
Comment thread onnxruntime/test/shared_lib/test_inference.cc Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@chilo-ms chilo-ms enabled auto-merge (squash) July 7, 2026 19:27
@chilo-ms chilo-ms merged commit 5eb4aee into main Jul 7, 2026
87 of 88 checks passed
@chilo-ms chilo-ms deleted the chilo-ms/fix-customop-forward-compat branch July 7, 2026 20:27
tianleiwu pushed a commit that referenced this pull request Jul 7, 2026
…29574)

### Description
Remove the blanket version check in CustomOpKernel that prevented custom
ops compiled against a newer ORT from loading on an older runtime.
Instead, cap the version passed to GetApi() at ORT_API_VERSION.

This aligns custom ops with the EP plugin ABI pattern where forward
compatibility is supported via runtime version detection. Individual
newer functions in OrtCustomOp (CreateKernelV2, InferOutputShapeFn,
GetMayInplace, etc.) are already gated by per-function version checks
throughout custom_ops.cc, making the blanket reject both redundant and
harmful.

The EP is responsible for not calling API functions newer than the
runtime version -- the same contract as the EP plugin interface.



### Motivation and Context
<!-- - Why is this change required? What problem does it solve?
- If it fixes an open issue, please link to the issue here. -->

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
tianleiwu added a commit that referenced this pull request Jul 9, 2026
This cherry-picks the following commits for the release:

| Commit ID | PR Number | Commit Title |
|-----------|-----------|-------------|
| 56f6fee | #29038 | [CUDA] QMoE GEMV fast path for batch-1 decode |
| a2c7c3b | #29081 | Fix QMoE CPU livelock by eliminating nested
intra-op parallelism |
| bd0cb9a | #28571 | [MLAS] KleidiAI fix igemm regression |
| 5eb4aee | #29574 | Fix CustomOp forward compatibility: cap version
instead of rejecting |
| 5f49a37 | #29274 | fix(ci): incorrect identity for azcopy |
| bb9ba7e | #29468 | Upgrade to Xcode 26 |
| 36c6b7e | #29450 | Fix brew install applesimutils failure by
trusting wix/brew tap |
| a491809 | #29575 | Don't echo command when setting VSO variable in
mac-cpu-packing-jobs.yml. |
| a06675e | #29609 | Fix web e2e (npm/vite) and Python DML CI
pipelines |

Also fixed version missed by version update script.

---------

Signed-off-by: Qxiang Xu <Qixiang.Xu@arm.com>
Signed-off-by: Jonathan Clohessy <Jonathan.Clohessy@arm.com>
Signed-off-by: Martin Klacer <martin.klacer@arm.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: tlwu <tlwu@example.com>
Co-authored-by: Martin Klacer <martin.klacer@arm.com>
Co-authored-by: Jonathan Clohessy <Jonathan.Clohessy@arm.com>
Co-authored-by: Damien Dooley <damien.dooley@arm.com>
Co-authored-by: Chi Lo <54722500+chilo-ms@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Sanaa Hamel <sanaahamel@microsoft.com>
Co-authored-by: Edward Chen <18449977+edgchen1@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants