Skip to content

[TRTLLM-14831][chore] Consolidate package bootstrap and relocate restricted deserialization - #17254

Open
YihuiLu512 wants to merge 2 commits into
NVIDIA:mainfrom
YihuiLu512:layout/T01-bootstrap-serialization
Open

[TRTLLM-14831][chore] Consolidate package bootstrap and relocate restricted deserialization#17254
YihuiLu512 wants to merge 2 commits into
NVIDIA:mainfrom
YihuiLu512:layout/T01-bootstrap-serialization

Conversation

@YihuiLu512

@YihuiLu512 YihuiLu512 commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Reduce the package root's mechanics to a single private bootstrap module, and move the restricted unpickler into the package that consumes it. Each change is described below together with the reasoning it rests on and what it changes for callers.

  1. tensorrt_llm/_bootstrap.py (new), tensorrt_llm/init.py

_common.py's _init() and the three setup functions that lived in init.py -- DLL directory, Python-library preload, vendored-triton_kernels precedence -- merge into one private bootstrap module. init.py drops from 176 to 103 lines and is now only the package's compatibility surface: the intentional re-exports and all.

The two existing phases keep their order, which is the constraint the file is arranged around: _prepare_environment() runs before import torch, _init() runs after the package's own imports, and its early-return guard is unchanged.

That ordering forces the one change here that is not a pure move. _bootstrap.py is imported ahead of torch, so its module scope is restricted to the standard library; a module-level import torch or from .bindings import MpiComm would load Torch and the compiled extension before phase 1 had prepared for them. Phase 2's four imports -- torch, tensorrt_llm.bindings, ._utils and .logger -- therefore move into _init()'s body. This defers statements, not any module's first import: _init() is the last statement of init.py, and all four are already imported earlier on the import tensorrt_llm._torch.models path. Tracing module completion order with -X importtime over import tensorrt_llm confirms it: 2393 modules on both sides, and the whole difference is +tensorrt_llm._bootstrap at the front and -tensorrt_llm._common where it used to sit.

_common.py is absent from legacy-files.txt while init.py is on it, so the three relocated functions land in ruff's scope instead of yapf's and are reformatted accordingly. That is formatting only and confined to those three functions; _init() was already ruff-clean and moves unchanged.

  1. tensorrt_llm/_common.py becomes a shim

The old path keeps a definition-free shim that re-exports _init and warns on import. The module is private, and every source of evidence that can be checked inside this repository is clean -- but one cannot be checked here, namely consumers outside the repository, and only the module's owner can answer for those. That question was never asked, so removing the path was never certifiable. Ten lines against a breakage nobody here can observe is the same asymmetry that keeps a shim on every public path in this migration, so the shim goes in rather than the question going to an owner.

The export set is recorded rather than computed: both names in the old module are underscored, so a private module has no computable public surface, and the shim re-exports the one symbol this repository itself consumed. _inited is deliberately left out -- it is mutable module state, and a re-export would bind the value once and then diverge from the guard it appears to mirror.

What the shim preserves is one function object, not a copy: _common._init is _bootstrap._init is tensorrt_llm._init. A copy would give the guard two _inited flags, and a call through the old path would run phase 2 -- custom op registration and MPI init -- a second time, which it is not designed for; calling _common._init() again is verified to be a no-op. import tensorrt_llm does not pull the shim in, since init.py now imports _bootstrap, so the DeprecationWarning still means "you named the old path" rather than firing for every user.

  1. tensorrt_llm/serialization.py moves to tensorrt_llm/llmapi/serialization.py

The restricted unpickler moves into the package that consumes it, and both consumers at HEAD are rewritten to the canonical path: llmapi/rlhf_utils.py, the only production consumer, and tests/unittest/llmapi/test_serialization.py. A stale reference in a model_engine.py comment is retargeted as well. Nothing in the tree goes through the shim -- in-repo references, lint lists, ownership rules and derived configs are all rewritten as if the old path had disappeared. The file gains the NVIDIA copyright header it never had, and the four allowlist module strings travel with it unchanged; later tasks of this migration update their contents at the new location.

Ownership moves with the code. That is the one effective-CODEOWNERS change in this commit and it is intended: serialization.py inherited the package-root default and now falls under llmapi/'s rule, whose team owns its only consumer and its only test. No file loses an owner. The legacy-files.txt entry likewise follows the implementation to the new path, so the module stays in yapf's scope and the entry count is unchanged at 765.

  1. tensorrt_llm/serialization.py becomes a shim

The old path keeps a definition-free shim over all seven public names, warning on import. serialization has no leading underscore, so it is a public module path and keeps a shim regardless of what the evidence says; what the measurement earns is a shorter deprecation window, and it is what fixes the export set -- with no evidence source naming a symbol, the supported surface falls back to the module's own public surface: BASE_EXAMPLE_CLASSES, Unpickler, dump, dumps, load, loads and register_approved_class.

A shim, and only a shim, preserves from tensorrt_llm import serialization. That form works today only because serialization is a submodule of the package; init.py never imports it, so the top-level re-export that rescues other modules' symbols cannot help here -- what is imported is the module itself, and that goes through the import finder.

Because the shim re-exports objects rather than copies, isinstance and pickle keep working: every name satisfies
tensorrt_llm.serialization.X is tensorrt_llm.llmapi.serialization.X, seven of seven, nothing is defined at the old path and no module is rewritten. The two module objects are necessarily distinct -- a re-export shim shares symbols, not identity -- so per-symbol identity is the assertion that holds, and it is the property pickle and isinstance actually depend on. The security boundary forwards too, not just the names: a payload dumped through either path loads through the other, and an unapproved class is still rejected when loaded through the shim. A shim that forwarded only the success path would quietly widen the boundary while every round-trip test passed.

  1. .pre-commit-config.yaml, pyproject.toml, ruff-legacy.toml

Regenerated from legacy-files.txt, so no derived config still names the retired path; check-configs passes and the ruff baseline needs no key renames. Both shims are new files and therefore not on the legacy list, which puts them in ruff's scope; their formatting is already what ruff produces, so the hooks leave them alone.

Left alone deliberately

version.py stays at the package root: setup.py, lock-file generation and the packaging metadata read that exact source path. _deprecation.py is confirmed absent at HEAD with no remaining reference.

Nothing outside the two deprecation warnings changes for callers: the top-level all is byte-identical and hashes identically at runtime, the api-stability reference diff is empty, the golden manifest's sha256 is unchanged, no test moves so node IDs, test lists and waives.txt are untouched, and the import graph keeps its five module-level cycles with no new cross-package edge and neither shim joining one. Against a build of the base commit with this change overlaid, test_serialization.py passes 6 before and after and pre-migration pickles replay 10 of 10. The eleventh class in that compatibility matrix, GreedyDecodingParams, does not exist at this commit -- the name appears nowhere in the repository except as a string in the allowlist. Left as-is and recorded for the task that updates it.

Dev Engineer Review

  • Consolidates package bootstrap logic in tensorrt_llm/_bootstrap.py.
  • Preserves bootstrap phase ordering and defers phase-two imports inside _init().
  • Keeps tensorrt_llm/__init__.py as the package compatibility surface.
  • Converts tensorrt_llm/_common.py into a deprecation shim.
  • Moves restricted serialization to tensorrt_llm/llmapi/serialization.py.
  • Preserves the top-level serialization API through a deprecation shim.
  • Updates consumers, comments, ownership rules, formatting configuration, and legacy-file configuration.
  • version.py remains unchanged.
  • Reported checks show unchanged exports, API-stability references, manifest hash, test identifiers, and import-cycle count.
  • Pre-migration pickles replay successfully for the tested compatibility matrix.
  • Both deprecated paths emit warnings on direct import.

QA Engineer Review

  • Modified test file: tests/unittest/llmapi/test_serialization.py.
  • Test functions present:
    • test_serialization_allowed_class
    • test_serialization_disallowed_class
    • test_serialization_basic_object
    • test_serialization_complex_object_allowed_class
    • test_serialization_complex_object_partially_allowed_class
    • test_serialization_complex_object_disallowed_class
  • No test-list, test-db/, qa/, or waives.txt changes were reported.
  • Coverage for these test functions in tests/integration/test_lists/ is unavailable.
  • Verdict: needs follow-up.

Description

Test Coverage

PR Checklist

Please review the following before submitting your PR:

  • PR description clearly explains what and why. If using CodeRabbit's summary, please make sure it makes sense.

  • PR Follows TRT-LLM CODING GUIDELINES to the best of your knowledge.

  • Test cases are provided for new code paths (see test instructions)

  • If PR introduces API changes, an appropriate PR label is added - either api-compatible or api-breaking. For api-breaking, include BREAKING in the PR title.

  • Any new dependencies have been scanned for license and vulnerabilities

  • CODEOWNERS updated if ownership changes

  • Documentation updated as needed

  • Update tava architecture diagram if there is a significant design change in PR.

  • The reviewers assigned automatically/manually are appropriate for the PR.

  • Please check this after reviewing the above items as appropriate for this PR.

GitHub Bot Help

To see a list of available CI bot commands, please comment /bot help.

…ricted deserialization

Reduce the package root's mechanics to a single private bootstrap module, and
move the restricted unpickler into the package that consumes it. Each change
is described below together with the reasoning it rests on and what it changes
for callers.

1) tensorrt_llm/_bootstrap.py (new), tensorrt_llm/__init__.py

_common.py's _init() and the three setup functions that lived in __init__.py
-- DLL directory, Python-library preload, vendored-triton_kernels precedence
-- merge into one private bootstrap module. __init__.py drops from 176 to 103
lines and is now only the package's compatibility surface: the intentional
re-exports and __all__.

The two existing phases keep their order, which is the constraint the file is
arranged around: _prepare_environment() runs before `import torch`, _init()
runs after the package's own imports, and its early-return guard is unchanged.

That ordering forces the one change here that is not a pure move.
_bootstrap.py is imported ahead of torch, so its module scope is restricted to
the standard library; a module-level `import torch` or `from .bindings import
MpiComm` would load Torch and the compiled extension before phase 1 had
prepared for them. Phase 2's four imports -- torch, tensorrt_llm.bindings,
._utils and .logger -- therefore move into _init()'s body. This defers
statements, not any module's first import: _init() is the last statement of
__init__.py, and all four are already imported earlier on the
`import tensorrt_llm._torch.models` path. Tracing module completion order with
-X importtime over `import tensorrt_llm` confirms it: 2393 modules on both
sides, and the whole difference is +tensorrt_llm._bootstrap at the front and
-tensorrt_llm._common where it used to sit.

_common.py is absent from legacy-files.txt while __init__.py is on it, so the
three relocated functions land in ruff's scope instead of yapf's and are
reformatted accordingly. That is formatting only and confined to those three
functions; _init() was already ruff-clean and moves unchanged.

2) tensorrt_llm/_common.py becomes a shim

The old path keeps a definition-free shim that re-exports _init and warns on
import. The module is private, and every source of evidence that can be
checked inside this repository is clean -- but one cannot be checked here,
namely consumers outside the repository, and only the module's owner can
answer for those. That question was never asked, so removing the path was
never certifiable. Ten lines against a breakage nobody here can observe is the
same asymmetry that keeps a shim on every public path in this migration, so
the shim goes in rather than the question going to an owner.

The export set is recorded rather than computed: both names in the old module
are underscored, so a private module has no computable public surface, and the
shim re-exports the one symbol this repository itself consumed. _inited is
deliberately left out -- it is mutable module state, and a re-export would
bind the value once and then diverge from the guard it appears to mirror.

What the shim preserves is one function object, not a copy:
`_common._init is _bootstrap._init is tensorrt_llm._init`. A copy would give
the guard two _inited flags, and a call through the old path would run phase 2
-- custom op registration and MPI init -- a second time, which it is not
designed for; calling _common._init() again is verified to be a no-op.
`import tensorrt_llm` does not pull the shim in, since __init__.py now imports
_bootstrap, so the DeprecationWarning still means "you named the old path"
rather than firing for every user.

3) tensorrt_llm/serialization.py moves to tensorrt_llm/llmapi/serialization.py

The restricted unpickler moves into the package that consumes it, and both
consumers at HEAD are rewritten to the canonical path: llmapi/rlhf_utils.py,
the only production consumer, and tests/unittest/llmapi/test_serialization.py.
A stale reference in a model_engine.py comment is retargeted as well. Nothing
in the tree goes through the shim -- in-repo references, lint lists, ownership
rules and derived configs are all rewritten as if the old path had
disappeared. The file gains the NVIDIA copyright header it never had, and the
four allowlist module strings travel with it unchanged; later tasks of this
migration update their contents at the new location.

Ownership moves with the code. That is the one effective-CODEOWNERS change in
this commit and it is intended: serialization.py inherited the package-root
default and now falls under llmapi/'s rule, whose team owns its only consumer
and its only test. No file loses an owner. The legacy-files.txt entry likewise
follows the implementation to the new path, so the module stays in yapf's
scope and the entry count is unchanged at 765.

4) tensorrt_llm/serialization.py becomes a shim

The old path keeps a definition-free shim over all seven public names, warning
on import. serialization has no leading underscore, so it is a public module
path and keeps a shim regardless of what the evidence says; what the
measurement earns is a shorter deprecation window, and it is what fixes the
export set -- with no evidence source naming a symbol, the supported surface
falls back to the module's own public surface: BASE_EXAMPLE_CLASSES,
Unpickler, dump, dumps, load, loads and register_approved_class.

A shim, and only a shim, preserves `from tensorrt_llm import serialization`.
That form works today only because serialization is a submodule of the
package; __init__.py never imports it, so the top-level re-export that rescues
other modules' symbols cannot help here -- what is imported is the module
itself, and that goes through the import finder.

Because the shim re-exports objects rather than copies, isinstance and pickle
keep working: every name satisfies
`tensorrt_llm.serialization.X is tensorrt_llm.llmapi.serialization.X`, seven
of seven, nothing is defined at the old path and no __module__ is rewritten.
The two module objects are necessarily distinct -- a re-export shim shares
symbols, not identity -- so per-symbol identity is the assertion that holds,
and it is the property pickle and isinstance actually depend on. The security
boundary forwards too, not just the names: a payload dumped through either
path loads through the other, and an unapproved class is still rejected when
loaded through the shim. A shim that forwarded only the success path would
quietly widen the boundary while every round-trip test passed.

5) .pre-commit-config.yaml, pyproject.toml, ruff-legacy.toml

Regenerated from legacy-files.txt, so no derived config still names the
retired path; check-configs passes and the ruff baseline needs no key renames.
Both shims are new files and therefore not on the legacy list, which puts them
in ruff's scope; their formatting is already what ruff produces, so the hooks
leave them alone.

Left alone deliberately

version.py stays at the package root: setup.py, lock-file generation and the
packaging metadata read that exact source path. _deprecation.py is confirmed
absent at HEAD with no remaining reference.

Nothing outside the two deprecation warnings changes for callers: the
top-level __all__ is byte-identical and hashes identically at runtime, the
api-stability reference diff is empty, the golden manifest's sha256 is
unchanged, no test moves so node IDs, test lists and waives.txt are untouched,
and the import graph keeps its five module-level cycles with no new
cross-package edge and neither shim joining one. Against a build of the base
commit with this change overlaid, test_serialization.py passes 6 before and
after and pre-migration pickles replay 10 of 10. The eleventh class in that
compatibility matrix, GreedyDecodingParams, does not exist at this commit --
the name appears nowhere in the repository except as a string in the
allowlist. Left as-is and recorded for the task that updates it.

Signed-off-by: Yihui Lu <269394165+YihuiLu512@users.noreply.github.com>
@YihuiLu512

Copy link
Copy Markdown
Collaborator Author

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63761 [ run ] triggered by Bot. Commit: 086d63e Link to invocation

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The change moves package initialization into a two-phase bootstrap module and relocates restricted pickle serialization under tensorrt_llm.llmapi. Compatibility shims preserve former module paths, while manifests, imports, tests, and source references use the new paths.

Changes

Package bootstrap initialization

Layer / File(s) Summary
Two-phase package bootstrap
tensorrt_llm/__init__.py, tensorrt_llm/_bootstrap.py
Environment preparation now runs before torch import. Post-import initialization handles custom libraries, MPI, and optional stack printing.
Initialization compatibility shim
tensorrt_llm/_common.py, tensorrt_llm/_torch/pyexecutor/model_engine.py
_common re-exports _init from _bootstrap and emits a deprecation warning. A source-reference comment points to _bootstrap.py.

Serialization module relocation

Layer / File(s) Summary
Restricted serialization implementation
tensorrt_llm/llmapi/serialization.py
Adds approved-class registration, restricted unpickling, and pickle load and dump helpers.
Compatibility and call-site migration
tensorrt_llm/serialization.py, tensorrt_llm/llmapi/rlhf_utils.py, tests/unittest/llmapi/test_serialization.py
The former module re-exports the relocated API. RLHF utilities and tests import the llmapi module.
Tooling manifest updates
.pre-commit-config.yaml, legacy-files.txt, pyproject.toml, ruff-legacy.toml
Tooling manifests now reference tensorrt_llm/llmapi/serialization.py.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

  • NVIDIA/TensorRT-LLM#17281: Both changes reduce eager initialization in tensorrt_llm/__init__.py, but use different mechanisms.

Suggested reviewers: schetlur-nv, bowenfu, brnguyen2

Sequence Diagram(s)

sequenceDiagram
  participant PythonImport
  participant tensorrt_llm.__init__
  participant _bootstrap
  participant torch
  participant NativeRuntime
  PythonImport->>tensorrt_llm.__init__: import package
  tensorrt_llm.__init__->>_bootstrap: _prepare_environment()
  _bootstrap->>_bootstrap: configure DLLs, Python library, and vendored triton_kernels
  tensorrt_llm.__init__->>torch: import torch
  tensorrt_llm.__init__->>_bootstrap: _init()
  _bootstrap->>NativeRuntime: load custom libraries and initialize MPI
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title follows the required format and clearly summarizes bootstrap consolidation and restricted deserialization relocation.
Description check ✅ Passed The description explains the changes, rationale, compatibility behavior, affected files, and test coverage in detail.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 4

🧹 Nitpick comments (8)
tensorrt_llm/_bootstrap.py (5)

163-174: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Annotate _print_stacks and move the period read above the closure.

_print_stacks has no return annotation. It also reads print_stacks_period from the enclosing scope, and that name is bound at line 171, after the definition. The current order works because the thread starts at line 174. Read the environment variable before the definition, or pass the period as an argument, so the closure does not depend on statement order.

♻️ Proposed reorder
-    def _print_stacks():
+    print_stacks_period = int(os.getenv("TRTLLM_PRINT_STACKS_PERIOD", "-1"))
+
+    def _print_stacks() -> None:
         counter = 0
         while True:
             time.sleep(print_stacks_period)
             counter += 1
             logger.error(f"Printing stacks {counter} times")
             print_all_stacks()
 
-    print_stacks_period = int(os.getenv("TRTLLM_PRINT_STACKS_PERIOD", "-1"))
     if print_stacks_period > 0:

As per coding guidelines: "Annotate every function, use None for non-returning functions".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/_bootstrap.py` around lines 163 - 174, Update the stack-printing
setup around `_print_stacks` by annotating the function with a `None` return
type and reading `TRTLLM_PRINT_STACKS_PERIOD` before the closure is defined, or
pass the period explicitly as an argument. Preserve the existing thread-start
behavior and positive-period guard.

Source: Coding guidelines


120-134: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Type log_level precisely.

object accepts any value and gives no useful checking. The value is forwarded to logger.set_level(), which indexes severity_map with it, so an invalid value fails inside the logger instead of at the call site. Use the severity type that logger.set_level accepts, for example str | None.

♻️ Proposed signature
-def _init(log_level: object = None) -> None:
+def _init(log_level: str | None = None) -> None:

As per coding guidelines: "avoid Any and unnecessary type ignores, ... use Literal, overload, TypeVar, or Protocol when appropriate".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/_bootstrap.py` around lines 120 - 134, Update the _init
function’s log_level annotation from object to the precise severity type
accepted by logger.set_level, such as str | None, while preserving the existing
optional forwarding behavior and logger.set_level call.

Source: Coding guidelines


48-49: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add return annotations to the phase-1 helpers.

_add_trt_llm_dll_directory, _preload_python_lib and _setup_vendored_triton_kernels have no return annotation. _prepare_environment and _init in the same file already use -> None. Annotate these three the same way for consistency.

♻️ Proposed annotations
-def _add_trt_llm_dll_directory():
+def _add_trt_llm_dll_directory() -> None:
-def _preload_python_lib():
+def _preload_python_lib() -> None:
-def _setup_vendored_triton_kernels():
+def _setup_vendored_triton_kernels() -> None:

As per coding guidelines: "Annotate every function, use None for non-returning functions".

Also applies to: 56-57, 81-82

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/_bootstrap.py` around lines 48 - 49, Add -> None return
annotations to the phase-1 helper functions _add_trt_llm_dll_directory,
_preload_python_lib, and _setup_vendored_triton_kernels, matching the existing
annotations on _prepare_environment and _init.

Source: Coding guidelines


103-110: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Restore sys.path with try/finally.

If import triton_kernels raises, line 110 never runs. The package root then stays at the front of sys.path for the rest of the process, and it shadows later imports of any top-level module that also exists under the repository root. The prior sys.modules deletion also leaves no cached triton_kernels, so the state after the failure is worse than before the call.

♻️ Proposed fix
     should_add_to_path = str(root) not in sys.path
     if should_add_to_path:
         sys.path.insert(0, str(root))
 
-    import triton_kernels  # noqa: F401
-
-    if should_add_to_path:
-        sys.path.remove(str(root))
+    try:
+        import triton_kernels  # noqa: F401
+    finally:
+        if should_add_to_path:
+            sys.path.remove(str(root))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/_bootstrap.py` around lines 103 - 110, Wrap the temporary path
modification and import in a try/finally block around the existing
triton_kernels import, ensuring the inserted root is removed whenever
should_add_to_path is true even if import triton_kernels raises. Preserve the
current path ordering and avoid changing the import behavior.

149-159: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Narrow exception types and chain the original exception.

The exception handler at these lines has two issues:

  1. raise ImportError(str(e) + msg) drops the original traceback. Use from e to chain exceptions.
  2. except Exception catches failures from torch.classes.load_library(), from importing ._torch.custom_ops, and from calling _register_fake(). All three failure modes report the same error message, but they have different causes. Per the coding guidelines, catch the narrowest possible exception type.

Separate the torch.classes.load_library() call into its own try-except block. torch.classes.load_library() raises OSError when the shared library fails to load (it uses ctypes.CDLL internally). The import and _register_fake() call can raise ImportError. Add from e to both handlers:

Proposed fix
     try:
         torch.classes.load_library(ft_decoder_lib)
+    except OSError as e:
+        msg = (
+            "\nFATAL: Decoding operators failed to load. This may be caused by an incompatibility "
+            "between PyTorch and TensorRT-LLM. Please rebuild and install TensorRT-LLM."
+        )
+        raise ImportError(str(e) + msg) from e
+
+    try:
         from ._torch.custom_ops import _register_fake
 
         _register_fake()
-    except Exception as e:
+    except ImportError as e:
         msg = (
             "\nFATAL: Decoding operators failed to load. This may be caused by an incompatibility "
             "between PyTorch and TensorRT-LLM. Please rebuild and install TensorRT-LLM."
         )
-        raise ImportError(str(e) + msg)
+        raise ImportError(str(e) + msg) from e
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/_bootstrap.py` around lines 149 - 159, Split the initialization
flow around torch.classes.load_library, ._torch.custom_ops import, and
_register_fake into separate handlers: catch OSError only for the shared-library
load and ImportError for the import/registration path. Preserve the existing
fatal message, and chain the original exception with from e in both ImportError
raises.

Sources: Coding guidelines, Linters/SAST tools

tensorrt_llm/_common.py (1)

15-28: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Reduce the dependence on unresolvable internal references.

The docstring cites "Epic §0.4 and §6.1" and "Epic decision D4 (b)". A reader with only the repository cannot resolve those sections. State the two constraints inline, for example: the shim must not define new objects, and it must not rewrite __module__, because both break object identity for pre-migration pickles. Keep the ticket IDs as pointers.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/_common.py` around lines 15 - 28, Update the module docstring in
the compatibility shim to replace the unresolved Epic section and decision
references with inline explanations that the shim must not define new objects or
rewrite __module__, because either breaks object identity for pre-migration
pickles. Preserve the existing ticket IDs as repository pointers and retain the
explicit-list/no-import-* constraint.
tests/unittest/llmapi/test_serialization.py (1)

3-3: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a regression test for the legacy tensorrt_llm.serialization shim.

Extend the registered tests/unittest/llmapi/test_serialization.py test. Assert identity for all seven re-exported names and assert that importing the shim emits DeprecationWarning. Existing tests cover canonical serialization only; compatibility coverage is insufficient.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unittest/llmapi/test_serialization.py` at line 3, Add a regression test
in the existing serialization test module for importing the legacy
tensorrt_llm.serialization shim. Verify that all seven re-exported names are
identical to their canonical tensorrt_llm.llmapi.serialization counterparts, and
capture the import to assert it emits DeprecationWarning while preserving the
existing canonical serialization tests.

Source: Path instructions

tensorrt_llm/llmapi/serialization.py (1)

16-21: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Declare the canonical serializer exports.

This module has no __all__. A wildcard import also exports io, pickle, re, and partial. Declare the intended serializer names and verify the API-stability fixture after the change.

Proposed export declaration
+__all__ = (
+    "BASE_EXAMPLE_CLASSES",
+    "register_approved_class",
+    "Unpickler",
+    "dump",
+    "dumps",
+    "load",
+    "loads",
+)

As per coding guidelines, “keep __all__ updated for public interfaces.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/llmapi/serialization.py` around lines 16 - 21, Add an __all__
declaration in serialization.py listing only the module’s intended public
serializer symbols, excluding imported helpers such as io, pickle, re, and
partial. Verify the API-stability fixture passes with the canonical export set.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tensorrt_llm/_common.py`:
- Line 1: Restore the copyright header year range at the file header to
2022-2026, preserving the original start year for this modified file.

In `@tensorrt_llm/llmapi/serialization.py`:
- Line 150: Update the serialization registry handling around the initializer
and the load()/loads() methods to use None as the omitted-registry sentinel,
resolving it to the shared baseline/registered approved-class mapping while
preserving an explicitly supplied empty mapping as default-deny. Ensure
register_approved_class() updates the registry used by default loads, and add
regression coverage verifying a registered class can round-trip through dumps()
and default loads()/loads().
- Around line 164-167: Update the approved-class resolution in the serializer’s
find_class method to replace broad regex matching such as ^torch.* with an exact
allowlist of permitted (module, name) pairs. Ensure serialization.loads can
resolve only explicitly approved torch symbols, rejecting torch.hub.load and all
other unlisted callables before deserialization proceeds, while preserving
approved non-torch module handling as appropriate.
- Line 127: Add type annotations to all six functions and methods lacking them:
_register_class (parameters dict and obj, return type), register_approved_class
(parameter obj, return type), Unpickler.__init__ (all parameters and return
type), Unpickler.find_class (parameters module and name, return type), load (all
parameters including file and return type), and loads (all parameters including
s and return type). Use dict[str, list[str]] for allowlist dictionaries,
list[str] | None for pattern lists, BinaryIO for file-like input streams, and
Any for pickle return values. Ensure Python 3.10+ syntax is used throughout to
comply with the module's strict mypy checking requirement.

---

Nitpick comments:
In `@tensorrt_llm/_bootstrap.py`:
- Around line 163-174: Update the stack-printing setup around `_print_stacks` by
annotating the function with a `None` return type and reading
`TRTLLM_PRINT_STACKS_PERIOD` before the closure is defined, or pass the period
explicitly as an argument. Preserve the existing thread-start behavior and
positive-period guard.
- Around line 120-134: Update the _init function’s log_level annotation from
object to the precise severity type accepted by logger.set_level, such as str |
None, while preserving the existing optional forwarding behavior and
logger.set_level call.
- Around line 48-49: Add -> None return annotations to the phase-1 helper
functions _add_trt_llm_dll_directory, _preload_python_lib, and
_setup_vendored_triton_kernels, matching the existing annotations on
_prepare_environment and _init.
- Around line 103-110: Wrap the temporary path modification and import in a
try/finally block around the existing triton_kernels import, ensuring the
inserted root is removed whenever should_add_to_path is true even if import
triton_kernels raises. Preserve the current path ordering and avoid changing the
import behavior.
- Around line 149-159: Split the initialization flow around
torch.classes.load_library, ._torch.custom_ops import, and _register_fake into
separate handlers: catch OSError only for the shared-library load and
ImportError for the import/registration path. Preserve the existing fatal
message, and chain the original exception with from e in both ImportError
raises.

In `@tensorrt_llm/_common.py`:
- Around line 15-28: Update the module docstring in the compatibility shim to
replace the unresolved Epic section and decision references with inline
explanations that the shim must not define new objects or rewrite __module__,
because either breaks object identity for pre-migration pickles. Preserve the
existing ticket IDs as repository pointers and retain the
explicit-list/no-import-* constraint.

In `@tensorrt_llm/llmapi/serialization.py`:
- Around line 16-21: Add an __all__ declaration in serialization.py listing only
the module’s intended public serializer symbols, excluding imported helpers such
as io, pickle, re, and partial. Verify the API-stability fixture passes with the
canonical export set.

In `@tests/unittest/llmapi/test_serialization.py`:
- Line 3: Add a regression test in the existing serialization test module for
importing the legacy tensorrt_llm.serialization shim. Verify that all seven
re-exported names are identical to their canonical
tensorrt_llm.llmapi.serialization counterparts, and capture the import to assert
it emits DeprecationWarning while preserving the existing canonical
serialization tests.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: f9601d36-7f07-4fe0-8431-716416ab78a8

📥 Commits

Reviewing files that changed from the base of the PR and between 60e7fca and 086d63e.

📒 Files selected for processing (12)
  • .pre-commit-config.yaml
  • legacy-files.txt
  • pyproject.toml
  • ruff-legacy.toml
  • tensorrt_llm/__init__.py
  • tensorrt_llm/_bootstrap.py
  • tensorrt_llm/_common.py
  • tensorrt_llm/_torch/pyexecutor/model_engine.py
  • tensorrt_llm/llmapi/rlhf_utils.py
  • tensorrt_llm/llmapi/serialization.py
  • tensorrt_llm/serialization.py
  • tests/unittest/llmapi/test_serialization.py

Comment thread tensorrt_llm/_common.py
}


def _register_class(dict, obj):

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.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

# First, locate and examine the serialization.py file
fd -t f "serialization.py" tensorrt_llm/llmapi/

Repository: NVIDIA/TensorRT-LLM

Length of output: 194


🏁 Script executed:

# Get an outline of the file to understand its structure
ast-grep outline tensorrt_llm/llmapi/serialization.py

Repository: NVIDIA/TensorRT-LLM

Length of output: 550


🏁 Script executed:

# Read the specific line ranges mentioned in the review comment
sed -n '120,150p' tensorrt_llm/llmapi/serialization.py | cat -n
sed -n '155,160p' tensorrt_llm/llmapi/serialization.py | cat -n
sed -n '185,215p' tensorrt_llm/llmapi/serialization.py | cat -n

Repository: NVIDIA/TensorRT-LLM

Length of output: 2687


🏁 Script executed:

# Check for mypy configuration in the repository
fd -t f "pyproject.toml|setup.cfg|mypy.ini|.mypy.ini" | head -10

Repository: NVIDIA/TensorRT-LLM

Length of output: 617


🏁 Script executed:

# Check if CODING_GUIDELINES.md exists and contains annotation requirements
find . -name "CODING_GUIDELINES.md" -type f

Repository: NVIDIA/TensorRT-LLM

Length of output: 180


🏁 Script executed:

# Check mypy configuration in pyproject.toml
sed -n '/\[tool.mypy\]/,/^\[/p' pyproject.toml | head -50

Repository: NVIDIA/TensorRT-LLM

Length of output: 550


🏁 Script executed:

# Read the entire serialization.py file to assess annotation status
cat -n tensorrt_llm/llmapi/serialization.py

Repository: NVIDIA/TensorRT-LLM

Length of output: 11911


🏁 Script executed:

# Check CODING_GUIDELINES.md for annotation requirements
grep -A 5 -B 2 "Annotate every function" CODING_GUIDELINES.md

Repository: NVIDIA/TensorRT-LLM

Length of output: 157


🏁 Script executed:

# Read CODING_GUIDELINES.md to find annotation guidance
cat CODING_GUIDELINES.md | grep -A 5 -B 2 "Annotate\|type annotation"

Repository: NVIDIA/TensorRT-LLM

Length of output: 706


🏁 Script executed:

# Check if serialization.py is included in mypy overrides (could be excluded)
sed -n '/\[\[tool.mypy.overrides\]\]/,/^\[\[/p' pyproject.toml

Repository: NVIDIA/TensorRT-LLM

Length of output: 1215


🏁 Script executed:

# Verify that serialization.py is not in any mypy exclude patterns
grep -r "serialization" pyproject.toml

Repository: NVIDIA/TensorRT-LLM

Length of output: 252


🏁 Script executed:

# Check if there's any type checking in place currently by checking imports in serialization.py
head -25 tensorrt_llm/llmapi/serialization.py

Repository: NVIDIA/TensorRT-LLM

Length of output: 1346


🏁 Script executed:

# Get the full mypy configuration for llmapi module if any
grep -A 20 "llmapi" pyproject.toml

Repository: NVIDIA/TensorRT-LLM

Length of output: 8581


Add required type annotations to all public and module-level functions in serialization.py.

Functions _register_class(), register_approved_class(), load(), and loads() have no parameter or return type annotations. The Unpickler.__init__() and find_class() methods also lack annotations. Provide precise Python 3.10+ types for all parameters and return values: use dict[str, list[str]] for the allowlist dictionaries, list[str] | None for pattern lists, BinaryIO for file-like input streams, and Any for pickle return values. The module is subject to global strict mypy checking and must comply with the coding guideline requirement to "annotate every function."

Functions requiring annotation:
  • Line 127: _register_class(dict, obj)
  • Line 137: register_approved_class(obj)
  • Lines 143–148: Unpickler.__init__()
  • Line 155: Unpickler.find_class(module, name)
  • Lines 185–193: load(file, ...)
  • Lines 204–213: loads(s, ...)
🧰 Tools
🪛 Ruff (0.16.0)

[error] 127-127: Function argument dict is shadowing a Python builtin

(A002)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/llmapi/serialization.py` at line 127, Add type annotations to
all six functions and methods lacking them: _register_class (parameters dict and
obj, return type), register_approved_class (parameter obj, return type),
Unpickler.__init__ (all parameters and return type), Unpickler.find_class
(parameters module and name, return type), load (all parameters including file
and return type), and loads (all parameters including s and return type). Use
dict[str, list[str]] for allowlist dictionaries, list[str] | None for pattern
lists, BinaryIO for file-like input streams, and Any for pickle return values.
Ensure Python 3.10+ syntax is used throughout to comply with the module's strict
mypy checking requirement.

Source: Coding guidelines

Comment thread tensorrt_llm/llmapi/serialization.py
Comment thread tensorrt_llm/llmapi/serialization.py
@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63761 [ run ] completed with state SUCCESS. Commit: 086d63e
/LLM/main/L0_MergeRequest_PR pipeline #51712 completed with status: 'FAILURE'

CI Report

⚠️ Multi-GPU Label Required:
Multi-GPU tests require the ci: full pre-merge approved label on this PR. Ask a member of NVIDIA/trt-llm-ci-approvers to add the label, then re-trigger CI with the same bot command (no rebase needed).

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@YihuiLu512

Copy link
Copy Markdown
Collaborator Author

/bot help

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

GitHub Bot Help

/bot [-h] ['run', 'kill', 'skip', 'reuse-pipeline'] ...

Provide a user friendly way for developers to interact with a Jenkins server.

Run /bot [-h|--help] to print this help message.

See details below for each supported subcommand.

Details

run [--reuse-test (optional)pipeline-id --disable-fail-fast --skip-test --stage-list "A10-PyTorch-1, xxx" --gpu-type "A30, H100_PCIe" --test-backend "pytorch, cpp" --add-multi-gpu-test --only-multi-gpu-test --disable-multi-gpu-test --post-merge --extra-stage "H100_PCIe-TensorRT-Post-Merge-1, xxx" --detailed-log --debug(experimental) --high-priority]

Launch build/test pipelines. All previously running jobs will be killed.

--reuse-test (optional)pipeline-id (OPTIONAL) : Allow the new pipeline to reuse build artifacts and skip successful test stages from a specified pipeline or the last pipeline if no pipeline-id is indicated. If the Git commit ID has changed, this option will be always ignored. The DEFAULT behavior of the bot is to reuse build artifacts and successful test results from the last pipeline.

--disable-reuse-test (OPTIONAL) : Explicitly prevent the pipeline from reusing build artifacts and skipping successful test stages from a previous pipeline. Ensure that all builds and tests are run regardless of previous successes.

--disable-fail-fast (OPTIONAL) : Disable fail fast on build/tests/infra failures.

--skip-test (OPTIONAL) : Skip all test stages, but still run build stages, package stages and sanity check stages. Note: Does NOT update GitHub check status.

--stage-list "A10-PyTorch-1, xxx" (OPTIONAL) : Only run the specified test stages. Supports wildcard * for pattern matching (e.g., "*PerfSanity*" matches all stages containing PerfSanity). Examples: "A10-PyTorch-1, xxx", "PerfSanity". The patterns "*", "*Post-Merge*", and "*PerfSanity*", including equivalent escaped or repeated-star forms and their use in comma-separated lists, require the ci: post-merge approved PR label. Note: Does NOT update GitHub check status.

--gpu-type "A30, H100_PCIe" (OPTIONAL) : Only run the test stages on the specified GPU types. Examples: "A30, H100_PCIe". Note: Does NOT update GitHub check status.

--test-backend "pytorch, cpp" (OPTIONAL) : Skip test stages which don't match the specified backends. Only support [pytorch, cpp, tensorrt, triton]. Examples: "pytorch, cpp" (does not run test stages with tensorrt or triton backend). Note: Does NOT update GitHub pipeline status.

--only-multi-gpu-test (OPTIONAL) : Only run the multi-GPU tests. Requires the ci: full pre-merge approved label on the PR (ask a member of NVIDIA/trt-llm-ci-approvers). Note: Does NOT update GitHub check status.

--disable-multi-gpu-test (OPTIONAL) : Disable the multi-GPU tests. Note: Does NOT update GitHub check status.

--add-multi-gpu-test (OPTIONAL) : Force run the multi-GPU tests in addition to running L0 pre-merge pipeline. Requires the ci: full pre-merge approved label on the PR (ask a member of NVIDIA/trt-llm-ci-approvers).

--post-merge (OPTIONAL) : Run the L0 post-merge pipeline instead of the ordinary L0 pre-merge pipeline. Requires the ci: post-merge approved PR label applied by an active member of NVIDIA/trt-llm-ci-approvers. The approval label remains in place when new commits are pushed.

--extra-stage "H100_PCIe-TensorRT-Post-Merge-1, xxx" (OPTIONAL) : Run the ordinary L0 pre-merge pipeline and specified test stages. Supports wildcard * for pattern matching. Examples: --extra-stage "H100_PCIe-TensorRT-Post-Merge-1, xxx", --extra-stage "Post-Merge". The patterns "*", "*Post-Merge*", and "*PerfSanity*", including equivalent escaped or repeated-star forms and their use in comma-separated lists, require the ci: post-merge approved PR label.

--detailed-log (OPTIONAL) : Enable flushing out all logs to the Jenkins console. This will significantly increase the log volume and may slow down the job.

--debug (OPTIONAL) : Experimental feature. Enable access to the CI container for debugging purpose. Note: Specify exactly one stage in the stage-list parameter to access the appropriate container environment. Note: Does NOT update GitHub check status.

--high-priority (OPTIONAL) : Run the pipeline with high priority. This option is restricted to authorized users only and will route the job to a high-priority queue.

kill

kill

Kill all running builds associated with pull request.

skip

skip --comment COMMENT

Skip testing for latest commit on pull request. --comment "Reason for skipping build/test" is required. IMPORTANT NOTE: This is dangerous since lack of user care and validation can cause top of tree to break.

reuse-pipeline

reuse-pipeline

Reuse a previous pipeline to validate current commit. This action will also kill all currently running builds associated with the pull request. IMPORTANT NOTE: This is dangerous since lack of user care and validation can cause top of tree to break.

@YihuiLu512

Copy link
Copy Markdown
Collaborator Author

/bot -h run

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

GitHub Bot Help

/bot [-h] ['run', 'kill', 'skip', 'reuse-pipeline'] ...

Provide a user friendly way for developers to interact with a Jenkins server.

Run /bot [-h|--help] to print this help message.

See details below for each supported subcommand.

Details

run [--reuse-test (optional)pipeline-id --disable-fail-fast --skip-test --stage-list "A10-PyTorch-1, xxx" --gpu-type "A30, H100_PCIe" --test-backend "pytorch, cpp" --add-multi-gpu-test --only-multi-gpu-test --disable-multi-gpu-test --post-merge --extra-stage "H100_PCIe-TensorRT-Post-Merge-1, xxx" --detailed-log --debug(experimental) --high-priority]

Launch build/test pipelines. All previously running jobs will be killed.

--reuse-test (optional)pipeline-id (OPTIONAL) : Allow the new pipeline to reuse build artifacts and skip successful test stages from a specified pipeline or the last pipeline if no pipeline-id is indicated. If the Git commit ID has changed, this option will be always ignored. The DEFAULT behavior of the bot is to reuse build artifacts and successful test results from the last pipeline.

--disable-reuse-test (OPTIONAL) : Explicitly prevent the pipeline from reusing build artifacts and skipping successful test stages from a previous pipeline. Ensure that all builds and tests are run regardless of previous successes.

--disable-fail-fast (OPTIONAL) : Disable fail fast on build/tests/infra failures.

--skip-test (OPTIONAL) : Skip all test stages, but still run build stages, package stages and sanity check stages. Note: Does NOT update GitHub check status.

--stage-list "A10-PyTorch-1, xxx" (OPTIONAL) : Only run the specified test stages. Supports wildcard * for pattern matching (e.g., "*PerfSanity*" matches all stages containing PerfSanity). Examples: "A10-PyTorch-1, xxx", "PerfSanity". The patterns "*", "*Post-Merge*", and "*PerfSanity*", including equivalent escaped or repeated-star forms and their use in comma-separated lists, require the ci: post-merge approved PR label. Note: Does NOT update GitHub check status.

--gpu-type "A30, H100_PCIe" (OPTIONAL) : Only run the test stages on the specified GPU types. Examples: "A30, H100_PCIe". Note: Does NOT update GitHub check status.

--test-backend "pytorch, cpp" (OPTIONAL) : Skip test stages which don't match the specified backends. Only support [pytorch, cpp, tensorrt, triton]. Examples: "pytorch, cpp" (does not run test stages with tensorrt or triton backend). Note: Does NOT update GitHub pipeline status.

--only-multi-gpu-test (OPTIONAL) : Only run the multi-GPU tests. Requires the ci: full pre-merge approved label on the PR (ask a member of NVIDIA/trt-llm-ci-approvers). Note: Does NOT update GitHub check status.

--disable-multi-gpu-test (OPTIONAL) : Disable the multi-GPU tests. Note: Does NOT update GitHub check status.

--add-multi-gpu-test (OPTIONAL) : Force run the multi-GPU tests in addition to running L0 pre-merge pipeline. Requires the ci: full pre-merge approved label on the PR (ask a member of NVIDIA/trt-llm-ci-approvers).

--post-merge (OPTIONAL) : Run the L0 post-merge pipeline instead of the ordinary L0 pre-merge pipeline. Requires the ci: post-merge approved PR label applied by an active member of NVIDIA/trt-llm-ci-approvers. The approval label remains in place when new commits are pushed.

--extra-stage "H100_PCIe-TensorRT-Post-Merge-1, xxx" (OPTIONAL) : Run the ordinary L0 pre-merge pipeline and specified test stages. Supports wildcard * for pattern matching. Examples: --extra-stage "H100_PCIe-TensorRT-Post-Merge-1, xxx", --extra-stage "Post-Merge". The patterns "*", "*Post-Merge*", and "*PerfSanity*", including equivalent escaped or repeated-star forms and their use in comma-separated lists, require the ci: post-merge approved PR label.

--detailed-log (OPTIONAL) : Enable flushing out all logs to the Jenkins console. This will significantly increase the log volume and may slow down the job.

--debug (OPTIONAL) : Experimental feature. Enable access to the CI container for debugging purpose. Note: Specify exactly one stage in the stage-list parameter to access the appropriate container environment. Note: Does NOT update GitHub check status.

--high-priority (OPTIONAL) : Run the pipeline with high priority. This option is restricted to authorized users only and will route the job to a high-priority queue.

kill

kill

Kill all running builds associated with pull request.

skip

skip --comment COMMENT

Skip testing for latest commit on pull request. --comment "Reason for skipping build/test" is required. IMPORTANT NOTE: This is dangerous since lack of user care and validation can cause top of tree to break.

reuse-pipeline

reuse-pipeline

Reuse a previous pipeline to validate current commit. This action will also kill all currently running builds associated with the pull request. IMPORTANT NOTE: This is dangerous since lack of user care and validation can cause top of tree to break.

@YihuiLu512

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63872 [ run ] triggered by Bot. Commit: 086d63e Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63872 [ run ] completed with state SUCCESS. Commit: 086d63e
/LLM/main/L0_MergeRequest_PR pipeline #51812 completed with status: 'UNSTABLE'

CI Report

⚠️ Multi-GPU Label Required:
Multi-GPU tests require the ci: full pre-merge approved label on this PR. Ask a member of NVIDIA/trt-llm-ci-approvers to add the label, then re-trigger CI with the same bot command (no rebase needed).

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

Link to invocation

@YihuiLu512

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@QiJune QiJune left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63888 [ run ] triggered by Bot. Commit: 086d63e Link to invocation

Comment thread legacy-files.txt

@BowenFu BowenFu left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The implementation move preserves bootstrap ordering and serializer behavior, while the old paths remain compatibility shims. Approved.

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63888 [ run ] completed with state FAILURE. Commit: 086d63e
/LLM/main/L0_MergeRequest_PR pipeline #51828 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@YihuiLu512

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63965 [ run ] triggered by Bot. Commit: 086d63e Link to invocation

@QiJune
QiJune enabled auto-merge (squash) August 5, 2026 08:53
@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63965 [ run ] completed with state SUCCESS. Commit: 086d63e
/LLM/main/L0_MergeRequest_PR pipeline #51901 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@QiJune

QiJune commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64051 [ run ] triggered by Bot. Commit: 086d63e Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64051 [ run ] completed with state FAILURE. Commit: 086d63e
/LLM/main/L0_MergeRequest_PR pipeline #51981 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@lori-ren

lori-ren commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64166 [ run ] triggered by Bot. Commit: 086d63e Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64166 [ run ] completed with state FAILURE. Commit: 086d63e
/LLM/main/L0_MergeRequest_PR pipeline #52083 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@YihuiLu512

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64351 [ run ] triggered by Bot. Commit: 086d63e Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64351 [ run ] completed with state SUCCESS. Commit: 086d63e
/LLM/main/L0_MergeRequest_PR pipeline #52245 completed with status: 'SUCCESS'

CI Report

Link to invocation

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@YihuiLu512

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 4

🧹 Nitpick comments (2)
tensorrt_llm/llmapi/serialization.py (1)

137-155: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document the public restricted-serialization API.

register_approved_class, Unpickler, load, and loads have no docstrings. Add Google-style docstrings that describe the allowlist parameters and the default-deny behavior. Document that approved_module_patterns authorizes all names in a matched module.

As per coding guidelines, use docstrings rather than comments for externally usable interfaces, and use Google-style docstrings for classes and functions.

Also applies to: 185-224

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/llmapi/serialization.py` around lines 137 - 155, Add
Google-style docstrings to the public APIs register_approved_class, Unpickler,
load, and loads, covering their allowlist parameters, default-deny behavior, and
the security boundary enforced by Unpickler.find_class. Explicitly state that
approved_module_patterns authorizes every name in a matched module, and replace
interface comments with docstrings where applicable.

Source: Coding guidelines

tensorrt_llm/_bootstrap.py (1)

48-56: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add None return annotations to procedures.

_add_trt_llm_dll_directory, _preload_python_lib, _setup_vendored_triton_kernels, and _print_stacks do not return values. Add -> None to each definition.

As per coding guidelines, “Annotate every function, use None for procedures.”

Also applies to: 81-113, 163-170

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/_bootstrap.py` around lines 48 - 56, Add -> None return
annotations to the procedure definitions _add_trt_llm_dll_directory,
_preload_python_lib, _setup_vendored_triton_kernels, and _print_stacks,
preserving their existing implementations.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tensorrt_llm/_bootstrap.py`:
- Around line 120-125: Update _init so _inited is not set until Torch import,
custom-op loading, fake registration, and MPI initialization all complete
successfully; ensure a failed setup does not cause later calls to return as
initialized, either by leaving _inited false or preserving and re-raising the
initialization failure.
- Around line 103-110: Update the import setup around triton_kernels so the
vendored root is always moved to index zero, even when it already exists later
in sys.path. Save its original position, remove the existing entry before
insertion, and wrap the import in a finally block that restores the prior
sys.path state.
- Around line 149-159: In the library-loading block, keep only
torch.classes.load_library(ft_decoder_lib) inside the try, catch OSError and
RuntimeError, and raise ImportError with the existing context using raise ...
from exc to preserve the cause. Move the _register_fake import and invocation
outside the try/except so registration failures propagate independently.

In `@tensorrt_llm/_common.py`:
- Around line 24-25: Correct the removal-schedule text by completing the
sentence about removal being tracked by ticket T25 (TRTLLM-14855), then state
the at-least-one-release compatibility window in a separate sentence. Do not add
definitions or otherwise rewrite the surrounding content.

---

Nitpick comments:
In `@tensorrt_llm/_bootstrap.py`:
- Around line 48-56: Add -> None return annotations to the procedure definitions
_add_trt_llm_dll_directory, _preload_python_lib, _setup_vendored_triton_kernels,
and _print_stacks, preserving their existing implementations.

In `@tensorrt_llm/llmapi/serialization.py`:
- Around line 137-155: Add Google-style docstrings to the public APIs
register_approved_class, Unpickler, load, and loads, covering their allowlist
parameters, default-deny behavior, and the security boundary enforced by
Unpickler.find_class. Explicitly state that approved_module_patterns authorizes
every name in a matched module, and replace interface comments with docstrings
where applicable.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 416854da-c26e-4fd7-84f5-5e50763fad18

📥 Commits

Reviewing files that changed from the base of the PR and between 1745a6e and 4d33343.

📒 Files selected for processing (12)
  • .pre-commit-config.yaml
  • legacy-files.txt
  • pyproject.toml
  • ruff-legacy.toml
  • tensorrt_llm/__init__.py
  • tensorrt_llm/_bootstrap.py
  • tensorrt_llm/_common.py
  • tensorrt_llm/_torch/pyexecutor/model_engine.py
  • tensorrt_llm/llmapi/rlhf_utils.py
  • tensorrt_llm/llmapi/serialization.py
  • tensorrt_llm/serialization.py
  • tests/unittest/llmapi/test_serialization.py
🚧 Files skipped from review as they are similar to previous changes (8)
  • tensorrt_llm/llmapi/rlhf_utils.py
  • legacy-files.txt
  • tests/unittest/llmapi/test_serialization.py
  • .pre-commit-config.yaml
  • tensorrt_llm/init.py
  • ruff-legacy.toml
  • pyproject.toml
  • tensorrt_llm/serialization.py

Comment on lines +103 to +110
should_add_to_path = str(root) not in sys.path
if should_add_to_path:
sys.path.insert(0, str(root))

import triton_kernels # noqa: F401

if should_add_to_path:
sys.path.remove(str(root))

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Place the vendored root first on every import.

If root already occurs later in sys.path, Line 103 skips insertion. Line 107 can then import an external triton_kernels before the vendored package. Remove the existing entry, insert it at index zero, and restore its prior position in a finally block.

Proposed fix
-    should_add_to_path = str(root) not in sys.path
-    if should_add_to_path:
-        sys.path.insert(0, str(root))
-
-    import triton_kernels  # noqa: F401
-
-    if should_add_to_path:
-        sys.path.remove(str(root))
+    root_str = str(root)
+    previous_index = sys.path.index(root_str) if root_str in sys.path else None
+    if previous_index is not None:
+        del sys.path[previous_index]
+    sys.path.insert(0, root_str)
+    try:
+        import triton_kernels  # noqa: F401
+    finally:
+        sys.path.pop(0)
+        if previous_index is not None:
+            sys.path.insert(previous_index, root_str)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
should_add_to_path = str(root) not in sys.path
if should_add_to_path:
sys.path.insert(0, str(root))
import triton_kernels # noqa: F401
if should_add_to_path:
sys.path.remove(str(root))
root_str = str(root)
previous_index = sys.path.index(root_str) if root_str in sys.path else None
if previous_index is not None:
del sys.path[previous_index]
sys.path.insert(0, root_str)
try:
import triton_kernels # noqa: F401
finally:
sys.path.pop(0)
if previous_index is not None:
sys.path.insert(previous_index, root_str)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/_bootstrap.py` around lines 103 - 110, Update the import setup
around triton_kernels so the vendored root is always moved to index zero, even
when it already exists later in sys.path. Save its original position, remove the
existing entry before insertion, and wrap the import in a finally block that
restores the prior sys.path state.

Comment on lines +120 to +125
def _init(log_level: object = None) -> None:
"""Phase 2: custom-op registration and MPI initialization, after imports."""
global _inited
if _inited:
return
_inited = True

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.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Do not mark initialization complete before fallible setup.

Line 125 runs before the Torch import, custom-op load, fake registration, and MPI initialization. If any step fails, later _init() calls return successfully although initialization did not complete. Set _inited only after successful initialization, or retain and re-raise a saved initialization failure.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/_bootstrap.py` around lines 120 - 125, Update _init so _inited
is not set until Torch import, custom-op loading, fake registration, and MPI
initialization all complete successfully; ensure a failed setup does not cause
later calls to return as initialized, either by leaving _inited false or
preserving and re-raising the initialization failure.

Comment on lines +149 to +159
try:
torch.classes.load_library(ft_decoder_lib)
from ._torch.custom_ops import _register_fake

_register_fake()
except Exception as e:
msg = (
"\nFATAL: Decoding operators failed to load. This may be caused by an incompatibility "
"between PyTorch and TensorRT-LLM. Please rebuild and install TensorRT-LLM."
)
raise ImportError(str(e) + msg)

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.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

For the PyTorch version declared by this project, what exception types can torch.classes.load_library() raise?

💡 Result:

The torch.classes.load_library function in PyTorch does not explicitly define a custom set of exception types that it raises. Instead, it relies on underlying mechanisms—specifically torch.ops.load_library and the Python ctypes module—to handle the loading of shared libraries [1][2]. Consequently, the primary exception type raised by torch.classes.load_library is OSError [3][2]. This exception occurs when the operating system encounters an error during the library loading process, such as when the specified file path cannot be found (e.g., "cannot open shared object file: No such file or directory") or when there are issues with the library's symbols (e.g., "undefined symbol" errors) [3][2]. Because torch.classes.load_library internally uses ctypes.CDLL to load the library, it may also propagate other exceptions standard to the Python runtime depending on the environment and the nature of the failure [2]. Users should be prepared to catch OSError and potentially other standard Python exceptions when calling this function [3][2].

Citations:


🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- candidate file ---'
sed -n '120,175p' tensorrt_llm/_bootstrap.py
printf '%s\n' '--- PyTorch version declarations ---'
rg -n --glob '!*lock*' --glob '!*.md' 'torch(==|>=|<=|~=|[[:space:]])|pytorch' pyproject.toml setup.py setup.cfg requirements* tensorrt_llm 2>/dev/null | head -120
printf '%s\n' '--- load_library call sites ---'
rg -n 'load_library|_register_fake' .

Repository: NVIDIA/TensorRT-LLM

Length of output: 16750


🌐 Web query:

PyTorch torch.classes.load_library implementation and documented exception behavior for the PyTorch version used by TensorRT-LLM

💡 Result:

The torch.classes.load_library function is a utility in PyTorch used to dynamically load C++ shared libraries into the Python process, enabling the registration of custom C++ classes and operators with the PyTorch JIT/TorchScript runtime [1][2]. Implementation Details The function is defined in torch/_classes.py as a wrapper around the internal C++ operator torch.ops.load_library [1]. When called, it invokes this underlying C++ routine to load the specified shared library (.so on Linux,.pyd on Windows) [1][3]. This library typically contains static global initialization code that registers custom classes with the PyTorch runtime [1]. Once successfully loaded, the library path is added to the torch.classes.loaded_libraries set, which allows for tracking of loaded dependencies [1]. Exception Behavior The function does not have complex, custom-defined exception behavior explicitly documented in its Python wrapper. Instead, it relies on the underlying C++ library loading mechanism (typically using platform-specific APIs like dlopen on Linux or LoadLibrary on Windows). Consequently, if the library cannot be found, if it fails to link, or if the initialization code within the library raises an error, the operation will raise a standard Python RuntimeError or OSError propagated from the underlying C++ loading process [1][3]. Context for TensorRT-LLM TensorRT-LLM is built to be compatible with specific versions of PyTorch, generally ranging between 2.9.x and 2.11.x (as of early 2026, depending on the specific release and build environment) [4][5]. Because TensorRT-LLM relies on these standard PyTorch versions, the behavior of torch.classes.load_library remains consistent with the upstream PyTorch implementation [1][6][7]. Users should ensure their environment matches the PyTorch version expected by their specific TensorRT-LLM wheel, as mismatches can lead to runtime environment inconsistencies [6][7]. Top results: [1][3][6][7][4][5]

Citations:


🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- dependency files ---'
git ls-files | rg '(^|/)(pyproject\.toml|setup\.py|setup\.cfg|requirements[^/]*|environment[^/]*)$' | head -80
printf '%s\n' '--- declared torch constraints ---'
for f in $(git ls-files | rg '(^|/)(pyproject\.toml|setup\.py|setup\.cfg|requirements[^/]*|environment[^/]*)$' | head -80); do
  rg -n -i 'torch|pytorch' "$f" || true
done
printf '%s\n' '--- bootstrap context ---'
cat -n tensorrt_llm/_bootstrap.py | sed -n '125,170p'
printf '%s\n' '--- related definitions and callers ---'
rg -n -C 4 '_register_fake|load_library|_bootstrap' tensorrt_llm

Repository: NVIDIA/TensorRT-LLM

Length of output: 34337


🌐 Web query:

site:github.com/pytorch/pytorch torch/_classes.py "def load_library" "torch.classes"

💡 Result:

The torch.classes module is a specialized namespace in PyTorch used for accessing custom C++ classes that have been registered with the PyTorch runtime [1]. The file torch/_classes.py defines the Classes class, which acts as this module and handles the dynamic discovery and exposure of these custom classes [1]. Key functions and concepts include: 1. torch.classes.load_library: This function is used to load a shared library (e.g., a.so or.dll file) into the current process [1]. Loading the library triggers the execution of global initialization code, which typically registers custom C++ classes using the torch::class API [1][2]. Once loaded, the library path is added to torch.classes.loaded_libraries [1]. 2. Dynamic Namespace Access: The torch.classes module uses a custom getattr implementation [1]. When you access an attribute (e.g., torch.classes.my_namespace), it dynamically returns a ClassNamespace object [1]. This allows PyTorch to handle class registrations that may occur at runtime after the initial module import [3]. 3. Relation to C++ Registration: Developers register C++ classes by instantiating torch::class in C++ code [2]. By specifying a namespace and class name (e.g., 'foo' and 'Bar'), the class becomes accessible in Python via torch.classes.foo.Bar [2]. While both torch.ops and torch.classes provide mechanisms for loading shared libraries to extend PyTorch, torch.ops is primarily used for custom operators, whereas torch.classes is used for custom C++ classes [1][4]. In many cases, torch.classes.load_library internally calls torch.ops.load_library to perform the actual dynamic loading [1].

Citations:


🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- all tracked dependency/config files mentioning torch ---'
git grep -n -i -E 'torch|pytorch' -- \
  'pyproject.toml' 'setup.py' 'setup.cfg' 'requirements*.txt' \
  '*requirements*.txt' 'environment*.yml' 'environment*.yaml' \
  'docker/**' '.github/**' 2>/dev/null | head -200 || true
printf '%s\n' '--- exact bootstrap block ---'
nl -ba tensorrt_llm/_bootstrap.py | sed -n '140,165p'
printf '%s\n' '--- exception handling and registration definitions ---'
git grep -n -C 5 -E 'load_library|_register_fake|register_fake' -- tensorrt_llm torch 2>/dev/null | head -240 || true

Repository: NVIDIA/TensorRT-LLM

Length of output: 44544


🏁 Script executed:

#!/bin/bash
set -eu
python3 - <<'PY'
from urllib.request import Request, urlopen

versions = ("v2.11.0", "v2.12.0", "v2.13.0a0")
paths = ("torch/_classes.py", "torch/_ops.py")
for version in versions:
    print(f"=== {version} ===")
    for path in paths:
        url = f"https://raw.githubusercontent.com/pytorch/pytorch/{version}/{path}"
        try:
            request = Request(url, headers={"User-Agent": "CodeRabbit-review-check"})
            text = urlopen(request, timeout=15).read().decode("utf-8")
        except Exception as exc:
            print(f"{path}: FETCH_ERROR {type(exc).__name__}: {exc}")
            continue

        lines = text.splitlines()
        matches = [
            index for index, line in enumerate(lines)
            if "def load_library" in line or "_dlopen" in line
        ]
        print(f"--- {path} ---")
        for index in matches:
            start = max(0, index - 3)
            end = min(len(lines), index + 28)
            print("\n".join(f"{number + 1}: {lines[number]}" for number in range(start, end)))
PY

Repository: NVIDIA/TensorRT-LLM

Length of output: 1251


🌐 Web query:

PyTorch v2.11.0 torch.classes.load_library raises OSError RuntimeError source _ops.py _classes.py

💡 Result:

When torch.classes.load_library raises an OSError or RuntimeError during the loading of a shared library, it is almost always caused by an issue within the library itself or the environment in which it is being loaded, rather than a bug in PyTorch's _classes.py or _ops.py internal logic [1][2]. Because torch.classes.load_library internally invokes torch.ops.load_library, which uses ctypes.CDLL(path) to load the object [2], these errors usually indicate one of the following root causes: 1. Missing Shared Dependencies: The most common cause for an OSError is that the shared library cannot be loaded because its own dependencies (such as CUDA libraries or other system files) are not found or are incompatible [3]. Ensure that your library's dependencies are correctly installed and that your LD_LIBRARY_PATH (on Linux) or system PATH (on Windows) includes the necessary directories [4][3]. 2. ABI Incompatibility: A frequent source of RuntimeError or symbol-related errors is a mismatch between the C++ ABI (Application Binary Interface) used to compile your custom library and the ABI used to build your installed version of PyTorch (often related to the _GLIBCXX_USE_CXX11_ABI flag) [5][6]. If your library uses a different ABI than the PyTorch binary, it will fail to load or resolve symbols [5][6]. You may need to recompile your library with -D_GLIBCXX_USE_CXX11_ABI=0 or 1 to match your PyTorch installation [5]. 3. Incorrect File Path: Ensure that the path provided to load_library is accurate and that the file actually exists [4]. Even if the file exists, the dynamic linker might fail if it is the wrong architecture or format for your system [4]. 4. Version Mismatch: If you are using dependent packages like torchaudio or torchvision, ensure they are strictly compatible with your installed version of PyTorch [6]. Mismatched versions of these packages frequently cause "undefined symbol" errors because they may be trying to link against incompatible internal PyTorch APIs [6]. To debug, you can inspect the specific exception message associated with the OSError, as it often provides details about which file is missing or which symbol failed to resolve [5][4][3]. Verification of your environment by confirming versions of torch and its associated libraries is a recommended first step [6].

Citations:


Narrow the exception boundary and preserve the original cause.

Keep only torch.classes.load_library(ft_decoder_lib) inside the try and handle its loading failures (OSError and RuntimeError). Move the import and _register_fake() outside the boundary so registration errors are not reported as library-load failures. Use raise ImportError(...) from exc.

🧰 Tools
🪛 Ruff (0.16.1)

[warning] 154-154: Do not catch blind exception: Exception

(BLE001)


[warning] 159-159: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/_bootstrap.py` around lines 149 - 159, In the library-loading
block, keep only torch.classes.load_library(ft_decoder_lib) inside the try,
catch OSError and RuntimeError, and raise ImportError with the existing context
using raise ... from exc to preserve the cause. Move the _register_fake import
and invocation outside the try/except so registration failures propagate
independently.

Sources: Coding guidelines, Linters/SAST tools

Comment thread tensorrt_llm/_common.py
Comment on lines +24 to +25
Removal is tracked by the removal ticket T25 (TRTLLM-14855) delivers; the compatibility window spans at least
one release (Epic decision D4 (b)). Do not add definitions, do not rewrite

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct the removal-schedule sentence.

Line 24 ends with “delivers”, so the sentence is incomplete. State the ticket and compatibility window as separate sentences.

Proposed fix
-Removal is tracked by the removal ticket T25 (TRTLLM-14855) delivers; the compatibility window spans at least
+Removal is tracked by ticket T25 (TRTLLM-14855). The compatibility window spans at least
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Removal is tracked by the removal ticket T25 (TRTLLM-14855) delivers; the compatibility window spans at least
one release (Epic decision D4 (b)). Do not add definitions, do not rewrite
Removal is tracked by ticket T25 (TRTLLM-14855). The compatibility window spans at least
one release (Epic decision D4 (b)). Do not add definitions, do not rewrite
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/_common.py` around lines 24 - 25, Correct the removal-schedule
text by completing the sentence about removal being tracked by ticket T25
(TRTLLM-14855), then state the at-least-one-release compatibility window in a
separate sentence. Do not add definitions or otherwise rewrite the surrounding
content.

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64370 [ run ] triggered by Bot. Commit: 4d33343 Link to invocation

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.

8 participants