From 142c6f4d8853c0679cfadbff03340cb4c8b7bfad Mon Sep 17 00:00:00 2001 From: Grant Ozolins Date: Wed, 15 Jul 2026 16:44:57 +1000 Subject: [PATCH 1/3] fix: return CURLM_OK from intercepted curl_multi_add_handle The real curl_multi_add_handle() returns CURLM_OK (0) on success. The CurlHook interception was declared : void and returned null. Guzzle >= 7.13 (CurlMultiHandler::addCurlHandle) strictly checks `\CURLM_OK !== $result` and throws a RequestException otherwise. Under php-vcr this call is rewritten to CurlHook::curl_multi_add_handle, so the null return produced: Unable to add the cURL handle to the cURL multi handler: No error (0). Returning \CURLM_OK mirrors the real function's contract. Older Guzzle (<= 7.9.x) discards the return value, so this is backwards-compatible. --- src/VCR/LibraryHooks/CurlHook.php | 7 +++++- tests/Unit/LibraryHooks/CurlHookTest.php | 27 ++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/VCR/LibraryHooks/CurlHook.php b/src/VCR/LibraryHooks/CurlHook.php index eea98b399..89b364eb8 100644 --- a/src/VCR/LibraryHooks/CurlHook.php +++ b/src/VCR/LibraryHooks/CurlHook.php @@ -184,13 +184,18 @@ public static function curlExec(\CurlHandle $curlHandle) * * @see http://www.php.net/manual/en/function.curl-multi-add-handle.php */ - public static function curlMultiAddHandle(\CurlMultiHandle $multiHandle, \CurlHandle $curlHandle): void + public static function curlMultiAddHandle(\CurlMultiHandle $multiHandle, \CurlHandle $curlHandle): int { if (!isset(self::$multiHandles[(int) $multiHandle])) { self::$multiHandles[(int) $multiHandle] = []; } self::$multiHandles[(int) $multiHandle][(int) $curlHandle] = $curlHandle; + + // Mirror the real curl_multi_add_handle() return contract. Callers such as + // Guzzle >= 7.13 strictly check `\CURLM_OK !== $result` and throw otherwise; + // returning void (null) here made that check fail with "No error (0)". + return \CURLM_OK; } /** diff --git a/tests/Unit/LibraryHooks/CurlHookTest.php b/tests/Unit/LibraryHooks/CurlHookTest.php index c9ddeb775..b78f1cbe5 100644 --- a/tests/Unit/LibraryHooks/CurlHookTest.php +++ b/tests/Unit/LibraryHooks/CurlHookTest.php @@ -441,6 +441,33 @@ function (Request $request) use ($testClass, &$callCount) { ); } + public function testCurlMultiAddHandleReturnsCurlmOk(): void + { + $this->curlHook->enable( + function (Request $request): Response { + return new Response('200'); + } + ); + + $curlHandle = curl_init('http://example.com'); + Assertion::notSame($curlHandle, false); + + $curlMultiHandle = curl_multi_init(); + Assertion::notSame($curlMultiHandle, false); + + // Real curl_multi_add_handle() returns CURLM_OK (0) on success. Guzzle >= 7.13 + // strictly checks `\CURLM_OK !== $result` and throws when it is not returned, + // so the intercepted call must mirror that contract rather than return void. + $result = curl_multi_add_handle($curlMultiHandle, $curlHandle); + + curl_multi_remove_handle($curlMultiHandle, $curlHandle); + curl_multi_close($curlMultiHandle); + + $this->curlHook->disable(); + + $this->assertSame(\CURLM_OK, $result, 'Intercepted curl_multi_add_handle should return CURLM_OK.'); + } + /** * @requires PHP 5.5.0 */ From a71f4a944e33241c4e6a0f12a5ec89c4992064de Mon Sep 17 00:00:00 2001 From: Grant Ozolins Date: Wed, 15 Jul 2026 17:19:19 +1000 Subject: [PATCH 2/3] fix phpcs report: use arrow function in test --- tests/Unit/LibraryHooks/CurlHookTest.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/Unit/LibraryHooks/CurlHookTest.php b/tests/Unit/LibraryHooks/CurlHookTest.php index b78f1cbe5..4ce8c68bf 100644 --- a/tests/Unit/LibraryHooks/CurlHookTest.php +++ b/tests/Unit/LibraryHooks/CurlHookTest.php @@ -444,9 +444,7 @@ function (Request $request) use ($testClass, &$callCount) { public function testCurlMultiAddHandleReturnsCurlmOk(): void { $this->curlHook->enable( - function (Request $request): Response { - return new Response('200'); - } + fn (Request $request): Response => new Response('200') ); $curlHandle = curl_init('http://example.com'); From 99da86d42632abe0e70bd0e3dd18f6be3db7051c Mon Sep 17 00:00:00 2001 From: Grant Ozolins Date: Wed, 15 Jul 2026 17:21:00 +1000 Subject: [PATCH 3/3] fix indentation --- tests/Unit/LibraryHooks/CurlHookTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/LibraryHooks/CurlHookTest.php b/tests/Unit/LibraryHooks/CurlHookTest.php index 4ce8c68bf..33e8d0de2 100644 --- a/tests/Unit/LibraryHooks/CurlHookTest.php +++ b/tests/Unit/LibraryHooks/CurlHookTest.php @@ -444,7 +444,7 @@ function (Request $request) use ($testClass, &$callCount) { public function testCurlMultiAddHandleReturnsCurlmOk(): void { $this->curlHook->enable( - fn (Request $request): Response => new Response('200') + fn (Request $request): Response => new Response('200') ); $curlHandle = curl_init('http://example.com');