Lesson 119 of 158 – Typed API Errors
75%

Typed API Errors

REST APIs can return different types of errors such as validation errors, authentication errors, authorization errors, and server errors. In a TypeScript React Native application, we can create interfaces for these error responses so that errors can be handled in a structured way.

Note: Typed API errors are useful when working with PHP REST APIs, Axios, authentication, forms, validation, and React Native applications.

1. What is an API Error?

An API error occurs when the server cannot successfully process a request.

For example:

  • Invalid login credentials
  • Missing required fields
  • Record not found
  • User does not have permission
  • Database or server problem

2. Why Type API Errors?

TypeScript interfaces allow us to describe the structure of an error returned by the REST API.

  • Better error handling
  • Better code completion
  • Consistent error structure
  • Easier form validation
  • Cleaner React Native code

3. Basic API Error Interface

interface ApiError {
    success: boolean;
    message: string;
}

This represents a simple error response containing a success flag and an error message.

4. PHP Error Response

A PHP REST API may return:

{
    "success": false,
    "message": "Student not found"
}

The corresponding TypeScript interface is:

interface ApiError {
    success: boolean;
    message: string;
}

5. Validation Error Response

Validation errors often contain multiple field-specific messages.

{
    "success": false,
    "message": "Validation failed",
    "errors": {
        "name": [
            "Name is required"
        ],
        "email": [
            "Valid email is required"
        ]
    }
}

6. Typed Validation Errors

interface ValidationErrors {
    [field: string]: string[];
}

interface ApiError {
    success: boolean;
    message: string;
    errors?: ValidationErrors;
}

The index signature allows different form fields to contain their own error messages.

7. Optional Error Properties

Not every API error needs to contain field validation errors. Therefore, errors can be optional.

interface ApiError {
    success: boolean;
    message: string;
    errors?: {
        [field: string]: string[];
    };
}

8. HTTP 400 Error

HTTP 400 Bad Request usually indicates that the request contains invalid data or is not correctly formed.

{
    "success": false,
    "message": "Invalid request"
}

The React Native application can display the returned message to the user.

9. HTTP 401 Error

HTTP 401 Unauthorized commonly means that authentication is missing or invalid.

{
    "success": false,
    "message": "Authentication required"
}

A React Native application may redirect the user to the login screen.

10. HTTP 403 Error

HTTP 403 Forbidden generally means the user is authenticated but does not have permission to perform the requested action.

{
    "success": false,
    "message": "Access denied"
}

11. HTTP 404 Error

HTTP 404 Not Found can be returned when a requested resource does not exist.

{
    "success": false,
    "message": "Student not found"
}

TypeScript can use the same ApiError interface.

12. HTTP 422 Validation Error

HTTP 422 Unprocessable Content is commonly used when the request is understood but the submitted data fails validation.

{
    "success": false,
    "message": "Validation failed",
    "errors": {
        "email": [
            "Email is required"
        ]
    }
}

13. HTTP 500 Error

HTTP 500 Internal Server Error indicates that the server encountered an unexpected problem.

{
    "success": false,
    "message": "Internal server error"
}

The server should not expose sensitive database or application details to the mobile application.

14. Axios Error Object

Axios provides an error object when an HTTP request fails.

try {

    const response = await api.get("/students");

} catch (error) {

    console.log(error);

}

We can inspect the server response through Axios error information.

15. Accessing the Axios Error Response

catch (error) {

    if (axios.isAxiosError(error)) {

        console.log(
            error.response?.status
        );

        console.log(
            error.response?.data
        );
    }
}

The response data can contain the structured API error.

16. Typed Axios Error Data

We can tell TypeScript what structure we expect in the API error response.

interface ApiError {
    success: boolean;
    message: string;
    errors?: {
        [field: string]: string[];
    };
}

if (axios.isAxiosError<ApiError>(error)) {

    console.log(
        error.response?.data.message
    );
}

17. Displaying a Server Error Message

catch (error) {

    if (axios.isAxiosError<ApiError>(error)) {

        const message =
            error.response?.data.message;

        console.log(message);
    }
}

The application can display a user-friendly message based on the response.

18. Handling Validation Errors

catch (error) {

    if (axios.isAxiosError<ApiError>(error)) {

        const errors =
            error.response?.data.errors;

        if (errors?.email) {
            console.log(errors.email[0]);
        }
    }
}

This can be used to show validation messages near form fields.

19. React Native Error State

const [errorMessage, setErrorMessage] =
    useState<string>("");

The error message can be displayed in the React Native UI.

{errorMessage !== "" && (
    <Text>{errorMessage}</Text>
)}

20. Handling Different Status Codes

if (axios.isAxiosError<ApiError>(error)) {

    const status =
        error.response?.status;

    if (status === 401) {
        console.log("Please login");
    }

    if (status === 403) {
        console.log("Access denied");
    }

    if (status === 404) {
        console.log("Record not found");
    }

    if (status === 422) {
        console.log("Validation failed");
    }
}

21. Network Errors

Sometimes the server does not return an HTTP response at all. For example, the device may have no internet connection.

if (axios.isAxiosError(error)) {

    if (!error.response) {
        console.log(
            "Network error or server unavailable"
        );
    }
}

22. Error Interface with Error Code

Some APIs may return an application-specific error code.

interface ApiError {
    success: boolean;
    message: string;
    code?: string;
}

Example:

{
    "success": false,
    "message": "Email already exists",
    "code": "EMAIL_EXISTS"
}

23. Creating a Reusable Error Handler

const getApiErrorMessage = (
    error: unknown
): string => {

    if (axios.isAxiosError<ApiError>(error)) {

        return (
            error.response?.data.message ??
            "Request failed"
        );
    }

    return "Something went wrong";
};

A reusable function prevents repeated error-handling code.

24. Using the Error Handler

try {

    await api.get("/students");

} catch (error) {

    const message =
        getApiErrorMessage(error);

    setErrorMessage(message);
}

The same function can be used by multiple screens.

25. API Error and Form Validation

A registration API may return field-specific validation errors.

interface ApiError {
    success: boolean;
    message: string;
    errors?: {
        name?: string[];
        email?: string[];
        mobile?: string[];
        password?: string[];
    };
}

React Native can display each error next to the appropriate input field.

26. Do Not Expose Server Details

The PHP server should return safe error messages to the mobile application.

Avoid returning:

  • Database passwords
  • SQL queries
  • JWT secrets
  • Server file paths
  • Internal stack traces

Prefer:

{
    "success": false,
    "message": "Internal server error"
}

27. Common Typed Error Mistakes

  • Assuming every error has the same properties.
  • Accessing error.response.data without checking for a response.
  • Using any for every error.
  • Ignoring HTTP status codes.
  • Displaying sensitive server errors to users.
  • Not handling network failures.
  • Not handling validation errors separately.

28. Complete Error Interfaces

interface ValidationErrors {
    [field: string]: string[];
}

interface ApiError {
    success: boolean;
    message: string;
    code?: string;
    errors?: ValidationErrors;
}

This structure can handle simple errors, application error codes, and field-level validation errors.

29. Complete Typed Axios Error Example

import axios from "axios";

interface ApiError {
    success: boolean;
    message: string;
    errors?: {
        [field: string]: string[];
    };
}

const loadStudents = async () => {

    try {

        const response =
            await api.get("/students");

        console.log(response.data);

    } catch (error) {

        if (axios.isAxiosError<ApiError>(error)) {

            const status =
                error.response?.status;

            const data =
                error.response?.data;

            if (status === 401) {
                console.log("Please login");
            } else if (status === 403) {
                console.log("Access denied");
            } else if (status === 404) {
                console.log("Students not found");
            } else {

                console.log(
                    data?.message ??
                    "Request failed"
                );
            }

        } else {

            console.log("Unexpected error");

        }
    }
};

30. Complete Typed API Error Flow

React Native
      ↓
Axios Request
      ↓
PHP REST API
      ↓
Validation / Authentication
      ↓
HTTP Error Status
      ↓
JSON Error Response
      ↓
Axios Error
      ↓
TypeScript ApiError
      ↓
React Native Error Message

For example, if a registration request contains an invalid email, the PHP API can return HTTP 422 with a structured validation response. Axios receives the response, TypeScript describes its structure using ApiError, and React Native can display the appropriate message to the user.

{
    "success": false,
    "message": "Validation failed",
    "errors": {
        "email": [
            "Valid email is required"
        ]
    }
}

This creates a consistent and type-safe error-handling system between the PHP REST API and React Native application.

📌 Key Points

  • API errors can be represented using TypeScript interfaces.
  • Validation errors can contain field-specific messages.
  • HTTP 400, 401, 403, 404, 422, and 500 can represent different error situations.
  • Axios provides the server response through its error object when available.
  • Use axios.isAxiosError() to identify Axios errors.
  • Network errors may occur without an HTTP response.
  • Typed errors improve React Native error handling.
  • Reusable error-handling functions reduce duplicate code.
  • Server errors should not expose sensitive information.
  • TypeScript can create a clear error contract between React Native and PHP REST APIs.

🧠 Quick Quiz

Question: Which Axios property normally contains the server response when an HTTP request fails?