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.
You probably want to add a catch clause to TestDriver.main
:
try {
service.logon();
} catch (RetrofitError e) {
System.out.println(e.getResponse().getStatus());
}
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.
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;
}
}
}