Skip to content

Fix after_request_complete getting nil env#179

Merged
hmcguire-shopify merged 1 commit into
masterfrom
hm-zkqwwukmtslyukwx
Jan 28, 2026
Merged

Fix after_request_complete getting nil env#179
hmcguire-shopify merged 1 commit into
masterfrom
hm-zkqwwukmtslyukwx

Conversation

@hmcguire-shopify
Copy link
Copy Markdown
Contributor

@hmcguire-shopify hmcguire-shopify commented Dec 4, 2025

Previously, when a request caused @request.read(client) to raise, after_request_complete callbacks would end up with a nil env (which can cause NoMethodErrors when assuming its always a Hash).

This commit fixes the NoMethodError possibility by ensuring the env returned is at least a Hash so that [] won't raise. Note that it still can't be treated as a valid Rack environment since the request wasn't able to finish parsing, but a Hash here is better than nil.

This commit fixes the NoMethodError possibility by only running the callback (and incrementing the request counter) if a valid environment was constructed.

Copy link
Copy Markdown

@stevenzelinli stevenzelinli left a comment

Choose a reason for hiding this comment

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

Don't have a ton of context in this area but this change and the explanation make sense to me 👍

Comment thread lib/pitchfork/http_server.rb Outdated
rescue => application_error
handle_error(client, application_error)
env
env || @request.env
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.

Suggested change
env || @request.env
env || @request&.env

If Pitchfork::HttpParser.new raises [an application_error], better to fall back to a nil than an error

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated to do || {} where the callback is called as we discussed 👍

Comment thread lib/pitchfork/http_server.rb Outdated
request_env = process_client(client, worker, prepare_timeout(worker))
worker.increment_requests_count
@after_request_complete&.call(self, worker, request_env)
@after_request_complete&.call(self, worker, request_env || {})
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.

Should we just skip the callback instead?

I expect many callback would fail on an empty hash about as much as on nil, because some mandatory keys (e.g. PATH_INFO would be missing).

Technically, if we failed to parse the request, there's no "after request" stage.

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.

Yeah, that's fair.

IMO it's probably worth doing the @request&.env "saving attempt" -- because malformed or not, we did receive a request, so the callback-author probably wants to know about it. If we've failed parsing the request it's clearly not going to be complete, but there's still a decent chance it has a useful amount of context.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Noting things we use it for:

  • worker_requests_count metric
  • OOBGC
  • OOMKiller

Since the worker's request_count is incremented on the line above I feel like it makes sense to continue allowing applications to emit that (although we could also make that conditional on the request parsing). The other two things seem less important for a request that fails to parse

@hmcguire-shopify hmcguire-shopify force-pushed the hm-zkqwwukmtslyukwx branch 3 times, most recently from 4701b38 to 53175e9 Compare December 9, 2025 17:28
Previously, when a request caused `@request.read(client)` to raise,
`after_request_complete` callbacks would end up with a `nil` `env`
(which can cause `NoMethodError`s when assuming its always a `Hash`).

This commit fixes the `NoMethodError` possibility by only running the
callback (and incrementing the request counter) if a valid environment
was constructed.
@hmcguire-shopify hmcguire-shopify merged commit d0e49a5 into master Jan 28, 2026
23 of 24 checks passed
@hmcguire-shopify hmcguire-shopify deleted the hm-zkqwwukmtslyukwx branch January 28, 2026 14:11
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.

5 participants