You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Two related issues with the PUT and GET commands that cause silent failures — no error, no output, no indication that anything went wrong.
Issue 1: GET does not support single file stage paths
Steps to reproduce
GET @mystage/oracle/somefile.log.gz fs:///tmp/download/
Expected behavior
The file is downloaded, or an error is shown if the path is invalid.
Actual behavior
No output, no error, no file downloaded.
Root cause
In driver/src/conn.rs, get_files() unconditionally appends / to the stage path:
if !location.path.ends_with('/'){
location.path.push('/');// turns file path into non-existent directory path}let list_sql = format!("LIST {location}");
When the user passes a specific file path like @mystage/oracle/file.gz, the code transforms it to @mystage/oracle/file.gz/, which matches nothing in LIST. The while loop never executes and an empty RowStatsIterator is returned with no error.
The silent failure is compounded in display.rs:186:
if rows.is_empty(){returnOk(());// empty result treated as success, no output to user}
Notes
GET @mystage/oracle/ (directory path with trailing /) works correctly
Snowflake's GET supports both single file and directory paths
Issue 2: PUT silently succeeds when local file does not exist
Steps to reproduce
PUT file:///tmp/nonexistent-file.csv @mystage/
Expected behavior
An error is shown: file not found.
Actual behavior
No output, no error, no file uploaded.
Root cause
In driver/src/conn.rs, put_files() uses glob::glob() to match local files. When the path matches nothing (file does not exist, wrong path, etc.), the for loop never executes and an empty RowStatsIterator is returned — same silent failure path as above.
Proposed fixes
Short term — add empty result checks:
// put_files: after the for loopif results.is_empty(){returnErr(Error::BadArgument(format!("no local files matched: {}", local_dsn.path())));}// get_files: after the while loop if results.is_empty(){returnErr(Error::BadArgument(format!("no files found at stage path: {}", stage)));}
Longer term — support single file paths in GET:
Remove the unconditional / append and handle both cases:
If stage path ends with / or is empty → directory mode (current behavior)
If stage path does not end with / → single file mode: skip prefix stripping, use basename as local filename
This requires fixing three places in get_files(): the LIST query, the prefix stripping logic, and the stage_file construction.
Summary
Two related issues with the
PUTandGETcommands that cause silent failures — no error, no output, no indication that anything went wrong.Issue 1:
GETdoes not support single file stage pathsSteps to reproduce
Expected behavior
The file is downloaded, or an error is shown if the path is invalid.
Actual behavior
No output, no error, no file downloaded.
Root cause
In
driver/src/conn.rs,get_files()unconditionally appends/to the stage path:When the user passes a specific file path like
@mystage/oracle/file.gz, the code transforms it to@mystage/oracle/file.gz/, which matches nothing inLIST. The while loop never executes and an emptyRowStatsIteratoris returned with no error.The silent failure is compounded in
display.rs:186:Notes
GET @mystage/oracle/(directory path with trailing/) works correctlyGETsupports both single file and directory pathsIssue 2:
PUTsilently succeeds when local file does not existSteps to reproduce
Expected behavior
An error is shown: file not found.
Actual behavior
No output, no error, no file uploaded.
Root cause
In
driver/src/conn.rs,put_files()usesglob::glob()to match local files. When the path matches nothing (file does not exist, wrong path, etc.), theforloop never executes and an emptyRowStatsIteratoris returned — same silent failure path as above.Proposed fixes
Short term — add empty result checks:
Longer term — support single file paths in
GET:Remove the unconditional
/append and handle both cases:/or is empty → directory mode (current behavior)/→ single file mode: skip prefix stripping, use basename as local filenameThis requires fixing three places in
get_files(): the LIST query, the prefix stripping logic, and thestage_fileconstruction.Environment
driver/src/conn.rs,cli/src/display.rs