Skip to content

[opentelemetry-php-contrib] auto-guzzle: "post hook invalid signature" when Client::transfer() throws synchronously #1988

Description

Describe your environment

PHP | 8.3+
open-telemetry/opentelemetry-auto-guzzle | 1.2.1 (also present on main)
open-telemetry/sdk | 1.x
ext-opentelemetry | 1.x
guzzlehttp/guzzle | 7.9 / 7.10

Steps to reproduce

GuzzleHttp\Client::transfer() can throw synchronously before it returns a
promise, because Client::applyOptions() runs outside transfer()'s
try/catch and validates request options. Any option that fails validation
triggers this path. Minimal reproducer (a numerically-indexed headers array
makes applyOptions() throw InvalidArgumentException):

$client = new \GuzzleHttp\Client();
$client->get('https://example.com/', ['headers' => ['invalid']]);
(Real-world triggers: invalid cookies, conflicting form_params/multipart,
malformed headers, etc.)

What is the expected behavior?

The client span is ended/recorded for the failed call, and no PHP warning is
emitted.

What is the actual behavior?

The auto-guzzle transfer post hook is declared with a non-nullable return
value parameter:


post: static function (Client $client, array $params, PromiseInterface $promise, ?Throwable $exception): void
When transfer() throws, the extension invokes the post hook with a null
return value. The runtime signature check fails, the post hook is skipped,
the span leaks (never ended/detached), and an E_CORE_WARNING is emitted:


Core Warning: GuzzleHttp\Client::transfer(): OpenTelemetry: post hook invalid
signature, class=GuzzleHttp\Client function=transfer in Unknown on line 0
Error trackers such as Sentry capture this as a fatal error.

Additional context

This is the same "post hook invalid / span leak when the instrumented function
throws" class that has already been fixed for other instrumentations:

auto-curl — #1531 → fix open-telemetry/opentelemetry-php-contrib#335
Symfony Messenger — open-telemetry/opentelemetry-php-contrib#267
Fix: make the promise parameter nullable and end the span on the synchronous
throw path. 

PR: open-telemetry/opentelemetry-php-contrib#629

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions