Skip to content

fix: Support local filesystem paths in model download/discovery#7390

Open
dmvevents wants to merge 1 commit intoai-dynamo:mainfrom
dmvevents:fix/local-path-and-empty-file-download
Open

fix: Support local filesystem paths in model download/discovery#7390
dmvevents wants to merge 1 commit intoai-dynamo:mainfrom
dmvevents:fix/local-path-and-empty-file-download

Conversation

@dmvevents
Copy link
Copy Markdown

@dmvevents dmvevents commented Mar 14, 2026

Summary

  • When a worker uses --model-path /shared/path/to/model, the frontend's model discovery calls from_hf() which passes the local path to the HuggingFace provider, causing a validation error
  • This PR adds an early check: if the path is absolute and exists on the filesystem, return it directly without HF download

Problem

HFValidationError: Repo id must be in the form 'repo_name' or 'namespace/repo_name': '/shared/nvrx-demo/nemotron-phase1-merged'

Fix

In lib/llm/src/hub.rs::from_hf():

if name.is_absolute() && name.exists() {
    tracing::info!("Using local model path: {model_name}");
    return Ok(name.to_path_buf());
}

Test plan

  • Verified that local FSx path models load correctly on TRT-LLM worker
  • Verify frontend model discovery works with local paths
  • Verify HF-hosted models still work (no regression)

Related issue: #7389

Summary by CodeRabbit

  • Bug Fixes
    • Fixed handling of absolute filesystem paths to be used directly without attempting unnecessary downloads or cache lookups.

When a TRT-LLM worker registers with --model-path /shared/path/to/model,
the frontend's download_config() passes the local path to from_hf(),
which treats it as a HuggingFace repo name and fails with
HFValidationError.

This fix adds an early check in from_hf(): if the path is an absolute
filesystem path that exists, return it directly without attempting
any HuggingFace download. This enables models stored on local/shared
filesystems (FSx Lustre, NFS, etc.) to be served without requiring
a HuggingFace repo.

Fixes part of ai-dynamo#7389

Signed-off-by: Anton <antonai@users.noreply.github.com>
@dmvevents dmvevents requested a review from a team as a code owner March 14, 2026 22:07
@copy-pr-bot
Copy link
Copy Markdown

copy-pr-bot bot commented Mar 14, 2026

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions
Copy link
Copy Markdown
Contributor

👋 Hi dmvevents! Thank you for contributing to ai-dynamo/dynamo.

Just a reminder: The NVIDIA Test Github Validation CI runs an essential subset of the testing framework to quickly catch errors.Your PR reviewers may elect to test the changes comprehensively before approving your changes.

🚀

@github-actions github-actions bot added external-contribution Pull request is from an external contributor fix labels Mar 14, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 14, 2026

Walkthrough

The from_hf function in lib/llm/src/hub.rs now includes an early-return mechanism that detects and handles absolute filesystem paths that exist locally. When such a path is found, it returns immediately without proceeding through HuggingFace download or cache/offline logic.

Changes

Cohort / File(s) Summary
Early-return path handling
lib/llm/src/hub.rs
Added early-return conditional to handle existing absolute filesystem paths, returning them directly before offline/cache logic processing (8 lines added).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰 A shortcut through the code I found,
When paths are real upon the ground,
No need to wander, search, or cache—
Just take the quick route, swift and rash!
Early returns make logic sound, 🌟

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding support for local filesystem paths in the model download/discovery flow.
Description check ✅ Passed The description covers the Overview (problem statement), Details (the specific fix with code), and mentions the related issue, though some test plan items are incomplete (marked as TODO).
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Tip

You can get early access to new features in CodeRabbit.

Enable the early_access setting to enable early access features such as new models, tools, and more.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/llm/src/hub.rs (1)

80-80: ⚠️ Potential issue | 🟠 Major

Please rebase this PR against main before merge.

Currently 1999 commits behind main, which far exceeds the recommended threshold of ~25 commits. Use git rebase origin/main to sync with latest changes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/llm/src/hub.rs` at line 80, The branch is far behind main and must be
rebased before merging; checkout the branch containing lib/llm/src/hub.rs (where
from_hf is defined), run git fetch origin && git rebase origin/main, resolve any
conflicts (especially around changes to from_hf or nearby functions), run the
test suite/lints, then force-push the rebased branch to update the PR.
🧹 Nitpick comments (1)
lib/llm/src/hub.rs (1)

84-90: Add a focused test for the new absolute-local-path fast path.

This behavior is core to the fix and currently has no direct unit coverage in this file. A targeted test would prevent regressions.

🧪 Example test addition
 #[cfg(test)]
 mod tests {
     use super::*;
@@
+    #[tokio::test]
+    async fn test_from_hf_existing_absolute_path_returns_directly() {
+        let path = std::env::temp_dir().join(format!("dynamo-local-model-{}", std::process::id()));
+        std::fs::create_dir_all(&path).unwrap();
+
+        let resolved = from_hf(&path, true).await.unwrap();
+        assert_eq!(resolved, path);
+
+        let _ = std::fs::remove_dir_all(&path);
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/llm/src/hub.rs` around lines 84 - 90, Add a unit test that exercises the
absolute-local-path fast path in lib/llm/src/hub.rs: create a real temporary
absolute path on disk and pass it as name (the variable used in the diff) and
assert the function returns that same PathBuf (the code path that does return
Ok(name.to_path_buf())); the test should call the same public function in hub.rs
that resolves model locations and verify the returned path equals the provided
absolute path and that no download logic is triggered (e.g., by not relying on
network or by asserting no downstream downloader was invoked).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lib/llm/src/hub.rs`:
- Around line 87-89: Replace the current absolute-path existence check that uses
name.exists() with a non-panicking IO-aware check: call name.try_exists() and
handle the Result, and only treat the path as a local model if try_exists()
returns Ok(true) and name.is_dir() is true; if try_exists() returns an Err
propagate or log the IO error appropriately so it doesn't silently fall through
to HF download, and ensure this change is applied to the branch that logs "Using
local model path: {model_name}" before returning the PathBuf (this affects the
code handling name, model_name and downstream update_dir()).

---

Outside diff comments:
In `@lib/llm/src/hub.rs`:
- Line 80: The branch is far behind main and must be rebased before merging;
checkout the branch containing lib/llm/src/hub.rs (where from_hf is defined),
run git fetch origin && git rebase origin/main, resolve any conflicts
(especially around changes to from_hf or nearby functions), run the test
suite/lints, then force-push the rebased branch to update the PR.

---

Nitpick comments:
In `@lib/llm/src/hub.rs`:
- Around line 84-90: Add a unit test that exercises the absolute-local-path fast
path in lib/llm/src/hub.rs: create a real temporary absolute path on disk and
pass it as name (the variable used in the diff) and assert the function returns
that same PathBuf (the code path that does return Ok(name.to_path_buf())); the
test should call the same public function in hub.rs that resolves model
locations and verify the returned path equals the provided absolute path and
that no download logic is triggered (e.g., by not relying on network or by
asserting no downstream downloader was invoked).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 909d6019-2f38-4d41-b578-b0f84345afba

📥 Commits

Reviewing files that changed from the base of the PR and between 0b66515 and 5b6af4e.

📒 Files selected for processing (1)
  • lib/llm/src/hub.rs

Comment on lines +87 to +89
if name.is_absolute() && name.exists() {
tracing::info!("Using local model path: {model_name}");
return Ok(name.to_path_buf());
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.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In Rust std::path::Path, how do exists()andtry_exists()differ, and doesexists() return false on permission-denied errors?

💡 Result:

  • Path::exists(&self) -> bool returns true only if the path exists and its metadata is accessible; it coerces any error to false (including permission errors and broken symlinks). So yes: exists() can return false on “permission denied”. [1]
  • Path::try_exists(&self) -> io::Result<bool> distinguishes “does not exist” from “couldn’t be determined”: it returns Ok(true) if it verified the path exists, Ok(false) if it verified it doesn’t (including broken symlinks), and Err(e) when existence can’t be confirmed/denied (e.g., permission denied on a parent directory). [1]

In other words, exists() is essentially “try_exists() but swallow errors as false.” [1]

Sources
[1] Rust standard library docs: std::path::Path::{exists, try_exists}. (doc.rust-lang.org)

Citations:


🏁 Script executed:

# First, verify the exact code at lines 87-89 in lib/llm/src/hub.rs
echo "=== Checking lib/llm/src/hub.rs around lines 87-89 ==="
if [ -f "lib/llm/src/hub.rs" ]; then
  sed -n '80,95p' lib/llm/src/hub.rs
else
  echo "File not found at lib/llm/src/hub.rs"
fi

Repository: ai-dynamo/dynamo

Length of output: 904


🏁 Script executed:

# Check the broader context of the from_hf function
echo "=== Function context ==="
if [ -f "lib/llm/src/hub.rs" ]; then
  sed -n '75,120p' lib/llm/src/hub.rs
fi

Repository: ai-dynamo/dynamo

Length of output: 2038


🏁 Script executed:

# Verify the downstream usage in model_card.rs
echo "=== Checking lib/llm/src/model_card.rs around lines 460-476 ==="
if [ -f "lib/llm/src/model_card.rs" ]; then
  sed -n '455,480p' lib/llm/src/model_card.rs
fi

Repository: ai-dynamo/dynamo

Length of output: 1113


🏁 Script executed:

# Search for all callers of from_hf() to understand the flow
echo "=== Searching for callers of from_hf ==="
rg "from_hf\(" -A 2 -B 2 lib/

Repository: ai-dynamo/dynamo

Length of output: 1436


Use try_exists() and validate the local path is a directory.

Path::exists() masks IO errors (permission denied, permission issues on shared filesystems) and returns false, potentially causing valid local paths to silently fall through to HF downloads. Additionally, this branch accepts any existing path including files, but downstream update_dir() expects a directory.

💡 Proposed fix
-    if name.is_absolute() && name.exists() {
-        tracing::info!("Using local model path: {model_name}");
-        return Ok(name.to_path_buf());
-    }
+    if name.is_absolute() {
+        match name.try_exists() {
+            Ok(true) if name.is_dir() => {
+                tracing::info!("Using local model path: {model_name}");
+                return Ok(name.to_path_buf());
+            }
+            Ok(true) => {
+                anyhow::bail!("Local model path must be a directory: {model_name}");
+            }
+            Ok(false) => {}
+            Err(e) => {
+                anyhow::bail!("Cannot access local model path '{model_name}': {e}");
+            }
+        }
+    }
📝 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
if name.is_absolute() && name.exists() {
tracing::info!("Using local model path: {model_name}");
return Ok(name.to_path_buf());
if name.is_absolute() {
match name.try_exists() {
Ok(true) if name.is_dir() => {
tracing::info!("Using local model path: {model_name}");
return Ok(name.to_path_buf());
}
Ok(true) => {
anyhow::bail!("Local model path must be a directory: {model_name}");
}
Ok(false) => {}
Err(e) => {
anyhow::bail!("Cannot access local model path '{model_name}': {e}");
}
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/llm/src/hub.rs` around lines 87 - 89, Replace the current absolute-path
existence check that uses name.exists() with a non-panicking IO-aware check:
call name.try_exists() and handle the Result, and only treat the path as a local
model if try_exists() returns Ok(true) and name.is_dir() is true; if
try_exists() returns an Err propagate or log the IO error appropriately so it
doesn't silently fall through to HF download, and ensure this change is applied
to the branch that logs "Using local model path: {model_name}" before returning
the PathBuf (this affects the code handling name, model_name and downstream
update_dir()).

@OAMchronicle
Copy link
Copy Markdown

I want to know when we can merge

@dmvevents
Copy link
Copy Markdown
Author

@OAMchronicle — The PR is ready from our end. The CodeRabbit review from March 14 left some comments — are those addressed from your perspective? If there are any remaining items, happy to resolve them. Otherwise this should be ready for final approval and merge.

@OAMchronicle
Copy link
Copy Markdown

@OAMchronicle — The PR is ready from our end. The CodeRabbit review from March 14 left some comments — are those addressed from your perspective? If there are any remaining items, happy to resolve them. Otherwise this should be ready for final approval and merge.

No, that wasn't me. I've already found a solution, though I'm not sure if it's the same problem you encountered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

external-contribution Pull request is from an external contributor fix size/XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants