37

I am trying to connect to rest service via retrofit in android application. I am getting responses. But when there is some error response from the service, conversion exception occurs and now I want to do some actions based on the response body. But I am getting response body as NULL. But retrofit log has a error message. Why is this happening.

D/Reftofit log(24856): OkHttp-Received-Millis: 1397527055676
D/Reftofit log(24856): OkHttp-Response-Source: NETWORK 200
D/Reftofit log(24856): OkHttp-Sent-Millis: 1397527055492
D/Reftofit log(24856): Server: Apache/2.2.22 (Ubuntu)
D/Reftofit log(24856): X-Powered-By: PHP/5.3.10-1ubuntu3.10
D/Reftofit log(24856): {"result":"Invalid Token ID"}

Code:

public void failure(RetrofitError retrofitError) {
    String response = null;
    TokenError tokenError = (TokenError) retrofitError.getBodyAs(TokenError.class);
    response = tokenError.getErrorDetails();
    Log.e(TAG, response);
    if (response != null && response.contains("Invalid Token ID")) {
        GroupDataProvider.getInstance().onFailure();
    }

}

Here I am getting tokenError as null. I don't know why? Do I need to set something with rest adapter so that the response will be passed to retrofit error object.

JJD
  • 50,076
  • 60
  • 203
  • 339
Satya
  • 1,239
  • 2
  • 11
  • 15

4 Answers4

76

Try this code:

@Override
public void failure(RetrofitError error) {
    String json =  new String(((TypedByteArray)error.getResponse().getBody()).getBytes());
    Log.v("failure", json.toString());
}

with Retrofit 2.0

@Override
public void onFailure(Call<Example> call, Throwable t) {
    String message = t.getMessage();
    Log.d("failure", message);
}
Cabezas
  • 9,329
  • 7
  • 67
  • 69
  • 3
    Simple and amazing. This line saved a complete class. – Chrishan Oct 22 '15 at 14:25
  • 1
    what is RestError class ?. i cannot import it – John Jul 07 '16 at 13:34
  • 2
    @Cabezas Be careful with the first example approach (Retrofit 1.9), as there is a bug when casting to a TypedByteArray if you are using LogLevel.NONE. See https://github.com/square/retrofit/issues/953 – fernandospr Aug 01 '16 at 13:09
5

if error in String format:

public Sring getErrorBodyAsString(RetrofitError error) {    
      return (String) error.getBodyAs(String.class)
}

if you need custom object:

class ErrorResponse {
   @SerializedName("error")
   int errorCode;

   @SerializedName("msg")
   String msg;
}

public T getErrorBody(RetrofitError error, Class<T> clazz) {    
      return (T) error.getBodyAs(clazz);
}
Victor Ponomarenko
  • 490
  • 1
  • 7
  • 12
3

Your server should return 4xx HTTP error code to get this working.

When your server returns HTTP 200 this mean successful response and it will be processed with onSuccess branch. Likely your object which you pass to Callback<Object> should be ready to handle both success and error result.

To make sure this is the case you can check if RetrofitError is actually a JsonParseException by adding next snippet:

public void failure(RetrofitError error) {
    Log.v(TAG, error.getMessage());
};
Sergii Pechenizkyi
  • 22,227
  • 7
  • 60
  • 71
  • `error.getMessage()` doesn't return the body sent from REST service but something like "406 Not Acceptable" (in case you receive a 406). See answer by Cabezas to actually get the body. – Ferran Maylinch Jan 22 '16 at 13:36
1

you need use getErrorStream() for this.

If the HTTP response indicates that an error occurred, getInputStream() will throw an IOException. Use getErrorStream() to read the error response. The headers can be read in the normal way using getHeaderFields().

Ref: github issue

LOG_TAG
  • 19,894
  • 12
  • 72
  • 105