[Bugfix] Fix _has_module to verify native deps via trial import#39873
[Bugfix] Fix _has_module to verify native deps via trial import#39873esmeetu wants to merge 2 commits into
Conversation
`_has_module` used `importlib.util.find_spec` which only checks whether a module spec exists on disk. For native-extension packages whose shared libraries are missing (e.g. `nixl_ep` without `libcudart.so.12`), `find_spec` succeeds but the real import crashes. Add a trial `importlib.import_module` after the `find_spec` pre-check so that `has_nixl_ep()` (and all other `has_*` guards) correctly return `False` when a package is installed but its native dependencies are unsatisfied. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: esmeetu <jasonailu87@gmail.com>
There was a problem hiding this comment.
Code Review
This pull request updates the _has_module utility in vllm/utils/import_utils.py to perform a trial import of the specified module instead of just checking for its existence via find_spec. This change ensures that native dependencies and shared libraries are correctly satisfied before reporting the module as available. I have no feedback to provide.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9a77e42a67
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| try: | ||
| importlib.import_module(module_name) | ||
| return True | ||
| except (ImportError, OSError) as exc: |
There was a problem hiding this comment.
Catch non-ImportError failures in availability probe
The new trial import in _has_module only handles ImportError/OSError, so optional modules that fail import with other exception types now crash capability checks instead of returning False. This is a real path in-tree: vllm/utils/deep_gemm.py explicitly documents/catches RuntimeError from vendored deep_gemm import (_C.init() failure), but has_deep_gemm() now routes through _has_module first and would raise before that fallback logic runs. This turns a best-effort feature probe into a startup/runtime hard failure for broken optional installs.
Useful? React with 👍 / 👎.
Tests cover: - Returns True for importable stdlib modules - Returns False for nonexistent modules - Returns False when find_spec succeeds but import raises ImportError (e.g. missing libcudart.so) - Returns False when import raises OSError - Result is cached across repeated calls Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: esmeetu <jasonailu87@gmail.com>
|
Real-world repro that this PR would fix: #39923. Summary: With this PR's trial-import change, Happy to test a nightly once this merges and report back. Thanks for the fix. |
|
Duplicate #39851 |
|
@benchislett yeah, it does solve that issue. But i think this PR introduce a robust way to avoid similar events happen. :) |
Summary
_has_modulepreviously usedimportlib.util.find_spec()which only checks whether a module spec exists on disk, but does not verify that the module can actually be importednixl_epinstalled withoutlibcudart.so.12),find_specreturns a valid spec but the real import crashes withImportErrorhas_nixl_ep()(and potentially otherhas_*guards) to returnTruewhen the module was not actually usable, leading to import-time crashes like:importlib.import_module()after thefind_specpre-check, catchingImportError/OSErrorand returningFalsewhen native dependencies are unsatisfied. The@cachedecorator ensures this only runs once per module name.Not a duplicate
No existing open PRs address this issue. Searched for
_has_module,find_spec, andhas_module ImportError.Test plan
AI disclosure
This PR was authored with AI assistance (Claude). The human submitter has reviewed all changed lines.
🤖 Generated with Claude Code