Failure to unzip when UNC path in use, leading to package installation failure in pak::pkg_install

Open
#745 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
38/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Stale
Tech stack
c, r

Research direction

Reproduce the failure with zip::unzip using the letter-drive and UNC-path examples. Read pkgdepends' install_package_plan, start_task_install, make_install_process, make_unzip_process, and R/install-verify-binary.R, then inspect the reported zip.c:184 failure. Done means the fs archive extracts successfully through pkgdepends and pak for a UNC library path, with an actionable error if extraction still fails.

Written by the indexing model from the issue text.

Description

feature

Error

I am encountering an error similar to #518 and #310. In these examples, the error was due to the user library path not being writeable. But I believe I am encountering a different issue.

Here are my session details:

R version 4.4.2 (2024-10-31 ucrt)
Platform: x86_64-w64-mingw32/x64
Running under: Windows 11 x64 (build 26100)

Matrix products: default


locale:
[1] LC_COLLATE=English_United States.utf8  LC_CTYPE=English_United States.utf8    LC_MONETARY=English_United States.utf8
[4] LC_NUMERIC=C                           LC_TIME=English_United States.utf8    

time zone: America/New_York
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
[1] compiler_4.4.2 tools_4.4.2 

Here is an example of the error:

path = tempdir()
path = gsub("C:", sprintf("//%s/C$", Sys.getenv("COMPUTERNAME")), path)
.libPaths(path)
.libPaths()
#> [1] "\\\\AW2024/C$/Users/AlecW/AppData/Local/Temp/RtmpgPK4Ui"
#> [2] "C:/Program Files/R/R-4.4.2/library"
install.packages("pak")
#> Installing package into '\\AW2024/C$/Users/AlecW/AppData/Local/Temp/RtmpgPK4Ui'
#> (as 'lib' is unspecified)
#> package 'pak' successfully unpacked and MD5 sums checked
#> 
#> The downloaded binary packages are in
#>  C:\Users\AlecW\AppData\Local\Temp\RtmpgPK4Ui\downloaded_packages
pak::pkg_install('fs')
#> ℹ Loading metadata database
#> ✔ Loading metadata database ... done
#>  
#> → Will install 1 package.
#> → Will download 1 CRAN package (413.43 kB).
#> + fs   1.6.5 [dl] (413.43 kB)
#> ℹ Getting 1 pkg (413.43 kB)
#> ✔ Cached copy of fs 1.6.5 (x86_64-w64-mingw32) is the latest build
#> Error: ! error in pak subprocess
#> Caused by error in `verify_extracted_package(filename, pkg_cache)`:
#> ! 
#> 'C:\Users\AlecW\AppData\Local\Temp\Rtmp6dheTX\file20e0342632ed/bin/windows/contrib/4.4/fs_1.6.5.zip'
#> is not a valid R package, it is an empty archive.

Created on 2025-02-27 with reprex v2.1.1

You might notice the strange handling in the second line; I am converting the path to use a UNC path, because I believe this to be the source of the error. In my particular case at work, we have network drives that are accessed commonly using UNC paths for greater consistency instead of letter drives, which can vary from user to user.

Expected behavior

Using the ordinary letter drive (in this case C:), we receive the ordinary outcome.

path = tempdir()
.libPaths(path)
.libPaths()
#> [1] "C:/Users/AlecW/AppData/Local/Temp/RtmpExT5JY"
#> [2] "C:/Program Files/R/R-4.4.2/library"
install.packages("pak")
#> Installing package into 'C:/Users/AlecW/AppData/Local/Temp/RtmpExT5JY'
#> (as 'lib' is unspecified)
#> package 'pak' successfully unpacked and MD5 sums checked
#> 
#> The downloaded binary packages are in
#>  C:\Users\AlecW\AppData\Local\Temp\RtmpExT5JY\downloaded_packages
pak::pkg_install('fs')
#> ℹ Loading metadata database
#> ✔ Loading metadata database ... done
#>  
#> → Will install 1 package.
#> → Will download 1 CRAN package (413.43 kB).
#> + fs   1.6.5 [dl] (413.43 kB)
#> ℹ Getting 1 pkg (413.43 kB)
#> ✔ Cached copy of fs 1.6.5 (x86_64-w64-mingw32) is the latest build
#> ✔ Installed fs 1.6.5  (74ms)
#> ✔ 1 pkg: added 1 [2.7s]

Created on 2025-02-27 with reprex v2.1.1

Problem details: pkgdepends and zip

I chose to post this issue in pak because there is precedent for the exact error message in other issues. But the underlying error is with zip, via pkgdepends.

Here is the full trace of the error:

<callr_error/rlib_error_3_0/rlib_error/error>
Error: 
! error in pak subprocess
Caused by error in `verify_extracted_package(filename, pkg_cache)`:
! C:\Users\AlecW\AppData\Local\Temp\Rtmp4GyF14\file76305a3a6e54/bin/windows/contrib/4.4/fs_1.6.5.zip is not a
valid R package, it is an empty archive.
---
Backtrace:
1. pak::pkg_install("fs")
2. pak:::remote(function(...) get("pkg_install_do_plan", asNamespace("pak"))(...), …
3. err$throw(res$error)
---
Subprocess backtrace:
 1. base::withCallingHandlers(cli_message = function(msg) { …
 2. get("pkg_install_do_plan", asNamespace("pak"))(...)
 3. proposal$install()
 4. pkgdepends::install_package_plan(plan, lib = private$library, num_workers = nw, …
 5. base::withCallingHandlers({ …
 6. pkgdepends:::handle_events(state, events)
 7. pkgdepends:::handle_event(state, i)
 8. proc$get_result()
 9. processx:::process_get_result(self, private)
10. private$post_process()
11. pkgdepends:::install_extracted_binary(filename, lib_cache, pkg_cache, lib, …
12. pkgdepends:::verify_extracted_package(filename, pkg_cache)
13. base::throw(pkg_error("{.path {filename}} is not a valid R package, it is an empty archive.", …
14. | base::signalCondition(cond)
15. global (function (e) …

I arrived at the source of the error by debugging through pkgdepends:::install_package_plan, start_task_install, make_install_process, make_unzip_process.

The unzip process actually fails silently, and it is not until verify_extracted_package(filename, pkg_cache) does an error raise, and only because the parent_path is empty (from verify_extracted_package)

But here is what we see when we run the unzip process manually, using either a regular path:

path = tempdir()
.libPaths(path)
install.packages('pkgdepends')
#> Installing package into 'C:/Users/AlecW/AppData/Local/Temp/RtmpYVDXaK'
#> (as 'lib' is unspecified)
#> also installing the dependencies 'callr', 'cli', 'curl', 'desc', 'filelock', 'jsonlite', 'lpSolve', 'pkgbuild', 'pkgcache', 'processx', 'ps', 'R6', 'zip'
#> package 'callr' successfully unpacked and MD5 sums checked
#> package 'cli' successfully unpacked and MD5 sums checked
#> package 'curl' successfully unpacked and MD5 sums checked
#> package 'desc' successfully unpacked and MD5 sums checked
#> package 'filelock' successfully unpacked and MD5 sums checked
#> package 'jsonlite' successfully unpacked and MD5 sums checked
#> package 'lpSolve' successfully unpacked and MD5 sums checked
#> package 'pkgbuild' successfully unpacked and MD5 sums checked
#> package 'pkgcache' successfully unpacked and MD5 sums checked
#> package 'processx' successfully unpacked and MD5 sums checked
#> package 'ps' successfully unpacked and MD5 sums checked
#> package 'R6' successfully unpacked and MD5 sums checked
#> package 'zip' successfully unpacked and MD5 sums checked
#> package 'pkgdepends' successfully unpacked and MD5 sums checked
#> 
#> The downloaded binary packages are in
#>  C:\Users\AlecW\AppData\Local\Temp\RtmpYVDXaK\downloaded_packages
library(pkgdepends)
prop = new_pkg_installation_proposal('fs', config = list(library = .libPaths()[[1L]]))
prop$download()
#> ℹ Loading metadata database
#> ✔ Loading metadata database ... done
#> ℹ Getting 1 pkg (413.43 kB)
#> ✔ Cached copy of fs 1.6.5 (x86_64-w64-mingw32) is the latest build
plan = prop$get_install_plan()
# Letter path succeeds
zip::unzip(zipfile = plan$file, exdir = path)
'fs' %in% dir(path)
#> [1] TRUE

Created on 2025-02-27 with reprex v2.1.1

... or a UNC path:

path = tempdir()
path = gsub("C:", sprintf("//%s/C$", Sys.getenv("COMPUTERNAME")), path)
.libPaths(path)
install.packages('pkgdepends')
#> Installing package into '\\AW2024/C$/Users/AlecW/AppData/Local/Temp/RtmpusLqCg'
#> (as 'lib' is unspecified)
#> also installing the dependencies 'callr', 'cli', 'curl', 'desc', 'filelock', 'jsonlite', 'lpSolve', 'pkgbuild', 'pkgcache', 'processx', 'ps', 'R6', 'zip'
#> package 'callr' successfully unpacked and MD5 sums checked
#> package 'cli' successfully unpacked and MD5 sums checked
#> package 'curl' successfully unpacked and MD5 sums checked
#> package 'desc' successfully unpacked and MD5 sums checked
#> package 'filelock' successfully unpacked and MD5 sums checked
#> package 'jsonlite' successfully unpacked and MD5 sums checked
#> package 'lpSolve' successfully unpacked and MD5 sums checked
#> package 'pkgbuild' successfully unpacked and MD5 sums checked
#> package 'pkgcache' successfully unpacked and MD5 sums checked
#> package 'processx' successfully unpacked and MD5 sums checked
#> package 'ps' successfully unpacked and MD5 sums checked
#> package 'R6' successfully unpacked and MD5 sums checked
#> package 'zip' successfully unpacked and MD5 sums checked
#> package 'pkgdepends' successfully unpacked and MD5 sums checked
#> 
#> The downloaded binary packages are in
#>  C:\Users\AlecW\AppData\Local\Temp\RtmpusLqCg\downloaded_packages
library(pkgdepends)
prop = new_pkg_installation_proposal('fs', config = list(library = .libPaths()[[1L]]))
prop$download()
#> ℹ Loading metadata database
#> ✔ Loading metadata database ... done
#> ℹ Getting 1 pkg (413.43 kB)
#> ✔ Cached copy of fs 1.6.5 (x86_64-w64-mingw32) is the latest build
plan = prop$get_install_plan()
# UNC path fails
zip::unzip(zipfile = plan$file, exdir = path)
#> Error in zip::unzip(zipfile = plan$file, exdir = path): zip error: Cannot extract entry `fs/` from archive `C:\Users\AlecW\AppData\Local\Temp\RtmpusLqCg\file284429c1b5f\bin\windows\contrib\4.4\fs_1.6.5.zip` in file zip.c:184
'fs' %in% dir(path)
#> [1] FALSE

Created on 2025-02-27 with reprex v2.1.1

Because the contents are not extracted, verify_extracted_package emits the error "{.path {filename}} is not a valid R package, it is an empty archive.".

Solution

I do not have a ready-made solution, because I believe the error is specific to the compiled code in the zip package.

Please let me know if you require any clarification! Ordinarily I would create a pull-request to try and remedy the situation, but I don't have any C++ experience.

Thank you very much!

Dominant language
C
Stars
821
Forks
88
Avg merge
17m
Merged PRs (30d)
1

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from r-lib/pak

All issues in r-lib/pak

Similar issues

More C issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.