Dear R-devel community,

I would like to propose adding support for capturing and displaying
custom error messages via the X-Error-Message HTTP response header
when downloading packages (via install.packages() and
download.file()).

Motivation:
Currently, when package downloads fail due to server-side policies
(security restrictions, policy violations, etc.), users only receive
generic HTTP status codes like "403 Forbidden". Repository
managers/administrators have no way to communicate specific failure
reasons to R users, making troubleshooting difficult.

Proposal:
Capture the error message via "X-Error-Message" header (if present)
from HTTP error responses and display them alongside standard error
messages.

Example output with the enhancement:
  Warning: cannot open URL 'https://...' HTTP status was '403 Forbidden'
   Error message: Requested item is quarantined by security policy

Industry Context:
This challenge is well-recognized across package management
ecosystems, and major tools have implemented similar solutions:

Custom error message headers (similar to this proposal):
- NuGet (.NET): Uses custom headers for server-side warnings/errors
https://github.com/NuGet/Home/wiki/%5BSpec%5D-Server-side-warnings-for-NuGet-client
- Hugging Face (ML models): Implements structured error messages in HTTP headers
https://huggingface.co/docs/huggingface_hub/en/package_reference/utilities#huggingface_hub.errors.HfHubHTTPError

Structured error formats (RFC 9457 "Problem Details"):
- Maven (Java): Recently added RFC 9457 support for detailed error reporting
https://github.com/apache/maven-resolver/pull/1502
- uv (Python): Implementing RFC 9457 for enhanced diagnostics
https://github.com/astral-sh/uv/pull/16199

Note: While RFC 9457 provides rich structured errors, a custom header
approach (as used by NuGet/Hugging Face) offers similar user benefits with
minimal implementation complexity and is more appropriate for R's architecture.

Implementation:
I have a working implementation that:

C-level changes (src/modules/internet/libcurl.c):
- Adds struct for per-URL error message storage
- Implements callback function for case-insensitive header capture
- Extends download_report_url_error() to include custom messages
- Maintains isolated error contexts for concurrent downloads (thread-safe)

R-level changes (src/library/utils/R/packages.R):
- Uses withCallingHandlers() to capture C-level warnings
- Preserves immediate warning display in interactive sessions

Testing:
- Added backward compatibility tests to tests/download.file.R
- Verified with servers sending X-Error-Message headers
- Tested concurrent downloads (install.packages with multiple packages)
- Confirmed backward compatibility when the header is absent
- Validated proper memory cleanup and error context isolation

Technical details:
- Header parsing: case-insensitive per HTTP spec
- Message length: truncates at 512 characters
- Performance: minimal overhead, context allocated only when needed
- Standards compliant: uses standard HTTP header mechanism
- Backward compatible: no behavior change when the header is absent

I am happy to provide the complete patch and discuss implementation details.

Would the R Core team and community be interested in this enhancement?


--
Best regards,
Julian Bermudez Valderrama,
Software Engineer at Sonatype.

______________________________________________
[email protected] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to