Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The Best Way to Debug Retrofit Error Messages

I'm new to Retrofit. I have used Volley, and I kind of like Retrofit. I was just about to select Retrofit when I ran into this very non-descriptive error message when trying to do a POST.

 Exception in thread "main" retrofit.RetrofitError
    at retrofit.RetrofitError.httpError(RetrofitError.java:37)
    at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:413)
    at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:282)
    at myapi.api.$Proxy7.logon(Unknown Source)
    at myapi.api.TestDriver.main(TestDriver.java:94)

Well, I must say that this type of error message is about as useful as a warm jacket in the Sahara.

Does anyone even know where to begin with debugging this type of message? I really am not about to delegate to a REST api that does not provide useful error messages.

like image 709
user3186731 Avatar asked Jan 12 '14 06:01

user3186731


3 Answers

Create a custom ErrorHandler for Retrofit.

I found that catching the error didn't provide a whole lot of extra information but creating a custom ErrorHandler for Retrofit allowed me to dig deeper into the actual error, like so:

class MyErrorHandler implements ErrorHandler {
  @Override public Throwable handleError(RetrofitError cause) {
    Response r = cause.getResponse();
    if (r != null && r.getStatus() == 401) {
      return new UnauthorizedException(cause);
    }
    return cause;
  }
}

RestAdapter restAdapter = new RestAdapter.Builder()
    .setEndpoint("https://api.github.com")
    .setErrorHandler(new MyErrorHandler())
    .setLogLevel(RestAdapter.LogLevel.FULL)  // Do this for development too.
    .build();

From the Custom Synchronous Error Handling section on Retrofit Page.

Set the Log Level to FULL as well, as shown in above config code.

like image 58
Joshua Pinter Avatar answered Oct 05 '22 05:10

Joshua Pinter


You probably want to add a catch clause to TestDriver.main:

try {
  service.logon();
} catch (RetrofitError e) {
  System.out.println(e.getResponse().getStatus());
}
like image 40
Jesse Wilson Avatar answered Oct 05 '22 04:10

Jesse Wilson


Unfortunately RetrofitError (1.6.1) was tricky. 401's made getResponse() always return null which made it hard to tell if its a connection issue or authentication issue. At least for me, I had to look at the message to get the 401 error. Hopefully this helps someone else trying to do something similar.

public class RetrofitErrorHandler implements ErrorHandler {

    @Override
    public Throwable handleError(RetrofitError cause) {

        if (cause.isNetworkError()) {
            if(cause.getMessage().contains("authentication")){
                //401 errors
                return  new Exception("Invalid credentials. Please verify login info.");
            }else if (cause.getCause() instanceof SocketTimeoutException) {
                //Socket Timeout
                return new SocketTimeoutException("Connection Timeout. " +
                        "Please verify your internet connection.");
            } else {
                //No Connection
                return new ConnectException("No Connection. " +
                        "Please verify your internet connection.");
            }
        } else {

            return cause;
        }
    }

}
like image 26
Kalel Wade Avatar answered Oct 05 '22 06:10

Kalel Wade