Advanced 25 min read

Handle Errors and Timeouts

By the end of this lesson, you'll be able to:

  • Handle a non-200 response with a clear, specific exception
  • Handle a CalloutException from a genuine network failure or timeout
  • Explain why these are two genuinely different failure modes

Prerequisites: "Parse the Response (JSON)"

Handling a non-200 response

public class CurrencyConversionException extends Exception {}

public Decimal convert(Decimal amountInZar, String targetCurrency) {
    HttpRequest request = new HttpRequest();
    request.setEndpoint('callout:Currency_API/convert?from=ZAR&to=' + targetCurrency + '&amount=' + amountInZar);
    request.setMethod('GET');

    HttpResponse response = new Http().send(request);

    if (response.getStatusCode() != 200) {
        throw new CurrencyConversionException(
            'Currency API returned status ' + response.getStatusCode() + ': ' + response.getBody()
        );
    }

    ConversionResponse parsed = (ConversionResponse) JSON.deserialize(response.getBody(), ConversionResponse.class);
    return parsed.convertedAmount;
}

Module 22's custom exception pattern, once more — CurrencyConversionException carries the actual status code and response body, so whoever catches it (or reads the debug log, Module 33) knows exactly what the external API said went wrong, e.g. an unrecognized currency code (Lesson 1's edge case).

Handling a network failure or timeout

public Decimal convert(Decimal amountInZar, String targetCurrency) {
    HttpRequest request = new HttpRequest();
    request.setEndpoint('callout:Currency_API/convert?from=ZAR&to=' + targetCurrency + '&amount=' + amountInZar);
    request.setMethod('GET');
    request.setTimeout(5000); // 5 seconds, well under the 10-second callout limit

    HttpResponse response;
    try {
        response = new Http().send(request);
    } catch (CalloutException e) {
        throw new CurrencyConversionException('Could not reach the currency service: ' + e.getMessage());
    }

    if (response.getStatusCode() != 200) {
        throw new CurrencyConversionException('Currency API returned status ' + response.getStatusCode());
    }

    ConversionResponse parsed = (ConversionResponse) JSON.deserialize(response.getBody(), ConversionResponse.class);
    return parsed.convertedAmount;
}

A CalloutException (Module 20's try/catch, applied here) means the request never even got a response at all — a genuine network failure, a DNS problem, or exceeding setTimeout's limit — a fundamentally different failure from "the API responded, but with an error status." Both get wrapped in the same CurrencyConversionException for a consistent interface to callers, but they're detected and handled at different points in the method.

Exercise

As a comment, explain the difference between a non-200 HttpResponse and a caught CalloutException.

Show hint

Think about whether a response was actually received in each case.

APEX

Handle Errors and Timeouts Quiz

1. What causes a CalloutException, as opposed to a non-200 HttpResponse?

Log in to submit the quiz and save your score.

My Notes

Log in to keep private notes on this lesson.

Questions about this lesson

No questions yet — be the first to ask.

Log in to ask a question about this lesson.

Summary

A real integration can fail in two distinct ways — the external API responds with an error, or the callout itself fails to complete at all — and this lesson handles both explicitly.