Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Shaden's avatar

Laravel 8 Http Client, custom Exception Messages

Since Laravel has changed from raw Guzzle Http, to the new Http Client, you cannot get custom exception messages. the Https Client only returns standard messages, as set in Symfony\Component\HttpFoundation\Response

so if you have an exception with code 400, all you get back from the Http client is "bad request". the same with all other codes.

My Question is, is it my way of handling exception that is wrong when I like to pass the 400 exception with my own explanation why it is 400, like the "user does not have enough money to proceed" or the user is now sleeping please call back after 2 pm" there is no Symfony exception for sleeping user who will be available after 2pm.

I read all the docs. and clearly the Http Client will not handle custom messages, like Guzzle does with response->getMessage().

I know I can just use Guzzle Http and forget about the Laravel Client. but isn't that waste of resources, Taylor had to only add the getMessage() to the new client, it is not going to break anything.

Thanks.

0 likes
12 replies
geraintp's avatar

to be clear guzzle is not handling custom HTTP status messages, and you're not even actually sending one, per say, all your sending is a status code, and in your request body some content that may or may not contain a message.

bases on the status code guzzle's throwing an exception. the ...->getMessage() is literally returning what guzzle sets on the exception when it throws it.

All guzzle is making is an exception message. but at no point are you actually using a custom HTTP status message.

see https://github.com/guzzle/guzzle/blob/de6f1e58e735754b888649495ed4cb9ae3b19589/src/Exception/RequestException.php#L98

you can access the underlying guzzle PSR HTTP response just by calling $request->toPsrResponse() as all the Http client is, is a wrapper to make guzzle easier to use.

and equally, you can retrieve your custom error message from the body payload just like guzzle does something like

if($request->failed()){
	  echo $request->json('message');
}

// "Doh! we're closed"

// assuming the response was something like

return response()->json([
     'message' => "Doh! we're closed",
], 400);

but if you still want to use exceptions you can just chain on ->throw() to the request.

try {
    $client = new \GuzzleHttp\Client();
    $reponse = $client->get('http://127.0.0.1:8000/api/exception');
} catch (\Throwable $th) {
    dd($th->getMessage());
}

// Client error: `GET http://127.0.0.1:8000/api/exception` resulted in a `400 Bad Request` response:\n
// {"message":"Doh! we're closed"}\n

try {
    $request = Http::get('http://127.0.0.1:8000/api/exception')
        ->throw();
} catch (\Throwable $th) {
    dd($th->getMessage());
}

// HTTP request returned status code 400:\n
// {"message":"Doh! we're closed"}\n
martinbean's avatar

@shaden Laravel has not “changed” from Guzzle to the new HTTP client. As you say yourself, you can just use Guzzle if you want to. The HTTP client is just a fluent, Laravel-y wrapper around Guzzle.

You can have the Laravel HTTP client throw exceptions if you want that: https://laravel.com/docs/8.x/http-client#throwing-exceptions

You can then catch the exception and also inspect the HTTP response if you want to get information from the response body.

Shaden's avatar

@geraintp Thanks for your reply, I will try to use the $request->toPsrResponse() and see if it works.

As to using a json response with code 400, and custom message, this is ok if you are not throwing the exception , in my case all exceptions are thrown, not with a custom json response, this where the problem happens, when consuming the API , if there is an exception thrown somewhere, even if you add custom message in the exception you still get the symfony standard message. If you test with Postman using cURL, you get the exact message you added in the Exception. Why can't Laravel Http Client d the same?

Shaden's avatar

@martinbean I know Guzzle is still there I am using it now. my original question is why Laravel Http client, cannot respond with custom messages, why the response ignores my custom exception message and uses the built in messages. The response body no where it has any custom messages. just the built in messages. Having the Http Client throw the exception , this just forwards the same exception. but thrown rather than in a response. Thanks anyway,

martinbean's avatar

@shaden If you had read the link I gave you, you’ll have seen that the original response is contained in the exception.

So, catch the exception. You can then inspect the response and pull out whatever JSON values you need:

use Illuminate\Http\Client\RequestException;

Route::get('/bar', function () {
    return response()->json([
        'message' => 'Something bad happened.',
    ], 400);
});

Route::get('/foo', function () {
    try {
        Http::get('http://localhost/bar')->throw();
    } catch (RequestException $e) {
        echo $e->response->json()['message']; // Something bad happened.
        exit;
    }
});
1 like
Shaden's avatar

@martinbean What I need is

Route::get('/bar', function () {
    try {
       any function()
    } catch (RequestException $e) {
       throw new AnyException(MYMESSAGE);
    }
});

The way you describe it ok if you only need to respond from route or controller, in my case i need to respond from deeply nested classes, meaning I have to chain back the response()->json all the way to the controller. maybe about four to five stops before the controller to respond. and get MYMESSAGE in the esponse.

martinbean's avatar

@shaden So grab the message and send it to your AnyException class instead of echo-ing it like I did.

I’ve literally shown you what you wanted: how to get the response from an exception.

Shaden's avatar

@martinbean Exactly, that's where the issue is, you never get your custom message, you only get the standard Symfony messages, as listed in Symfony\Component\HttpFoundation\Response;

so if your code is 400 you get the message "BAD_REQUEST" , 404 ="NOT_FOUND" and so on. if you put none standard code like 700, the client does not recognize it and throws an error of non standard code .

Try it..

martinbean's avatar
Level 80

@shaden FFS, I did try it and showed you how to get the response from the request you made!

So, again since you’ve clearly missed it, to get the response of the request and not the exception message, use this:

// This will get the message from the response JSON, which is what you want
$message = $e->response->json()['message'];

And not this:

// This will return the exception message, NOT the message from the response JSON
$message = $e->getMessage();
Shaden's avatar

Hi

Thanks, Yeah It Worked Thanks a Ton for your help

1 like

Please or to participate in this conversation.