Skip to content

Preserve URI parse error info in error source chain#4025

Open
veeceey wants to merge 1 commit intohyperium:masterfrom
veeceey:fix/issue-3043-preserve-uri-error-info
Open

Preserve URI parse error info in error source chain#4025
veeceey wants to merge 1 commit intohyperium:masterfrom
veeceey:fix/issue-3043-preserve-uri-error-info

Conversation

@veeceey
Copy link
Copy Markdown

@veeceey veeceey commented Feb 23, 2026

Fixes #3043

When hyper parsed an HTTP request with an invalid URI, it would create a Parse(Uri) error but discard the original http::uri::InvalidUri error. This meant error.source() returned None, making it impossible to get the actual reason the URI was invalid.

Changed Parse::Uri to carry an Option<Cause> so the original InvalidUri or InvalidUriParts error flows through to Error::source(). The error message and Display output are unchanged - the improvement is only visible through the Error::source() chain.

Added a test that verifies error.source() returns the original http::uri::InvalidUri:

running 86 tests
...
test error::tests::uri_error_preserves_source ... ok
...
test result: ok. 86 passed; 0 failed; 0 ignored

@veeceey
Copy link
Copy Markdown
Author

veeceey commented Mar 10, 2026

hey, just checking in — is there anything else needed from my side?

When an invalid URI is parsed by the http crate, the InvalidUri error
contains useful details about what part of the URI was invalid. Previously
this information was discarded when converting to hyper::Error.

Now the original InvalidUri/InvalidUriParts error is stored as the
source of the hyper::Error, making it available through the standard
Error::source() chain and downcastable to the concrete type.

Closes hyperium#3043
@veeceey veeceey force-pushed the fix/issue-3043-preserve-uri-error-info branch from 9915783 to 51998bd Compare March 18, 2026 05:20
#[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
VersionH2,
Uri,
Uri(Option<Cause>),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this feels a bit unexpected. I'd expect all these variants to stay thin without allocations, and the Cause would only ever be used in with().

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yeah that's a fair point — adding the Option to the Parse variant bloats the enum for all variants even though it's only ever Some during the brief From conversion. I'll rework it so Parse::Uri stays thin and instead thread the cause through a separate path into Error::with(). Give me a bit to push the updated approach.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Dug into this more and it's trickier than I initially thought. The issue is that parse() returns ParseResult<T> = Result<_, Parse>, not Result<_, Error>. So the URI cause needs to survive through Parse before getting converted to Error at the boundary in io.rs.

Alternatives I looked at:

  1. Change ParseResult to use Error instead of Parse — lets us skip the intermediary entirely, but it touches the Http1Transaction trait + every parse call site. Pretty invasive.
  2. Handle URI parsing manually (replace ? with explicit map_err) — still can't return an Error from parse().
  3. Current approach: Option<Cause> on Parse::Uri — adds ~16 bytes to the Parse enum. The Some only exists briefly between From<InvalidUri> and From<Parse> for Error where it gets moved into .with().

If the enum size bump is a dealbreaker, option 1 is probably the right long-term fix but it's a bigger refactor. Happy to go whichever direction you prefer — or close this if you'd rather tackle it as part of a broader error rework.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

URI parse errors should preserve information from the HTTP crate

2 participants