Skip to content

Error Handling ​

This guide outlines the strategies and patterns used to handle different types of errors in the Bagisto Headless storefront, ensuring a resilient and user-friendly experience.

Overview ​

The storefront implements a multi-layered error handling strategy that covers data fetching, network connectivity, and user input validation. Our goal is to prevent application crashes, provide clear feedback to the user, and maintain a robust state.

1. GraphQL Errors ​

Since we interact with the Bagisto backend exclusively through GraphQL, handling API-level errors is critical.

Handling GraphQL Context ​

GraphQL queries often return a 200 OK HTTP status even if the request partially failed. We handle this in our custom fetch utilities by checking the data and errors arrays.

File: src/utils/fetch-handler.ts

typescript
if (!response.ok) {
  return {
    data: null,
    error: {
      status: response?.status,
      message: result?.error || "Something went wrong",
    },
  };
}

Mutation Side-Effects ​

When using useMutation, we provide onSuccess and onError callbacks to give users immediate feedback via the custom toast system.

typescript
const { mutateAsync } = useMutation({
  onSuccess: (res) => {
    if (!res?.data?.success) {
      showToast(res?.message, "danger");
    }
  },
  onError: (err) => {
    showToast(err.message ?? "An unexpected error occurred", "danger");
  }
});

2. Network & Application Errors ​

For critical failures that prevent a page from rendering, we use Next.js's built-in error boundary system.

Error Boundaries ​

We use error.tsx files located in the app/ directory segments to catch runtime errors and provide a fallback UI that doesn't break the entire site.

File: src/app/(public)/error.tsx

  • User-Friendly Message: "Oh no! There was an issue with our storefront."
  • Recovery Action: Provides a "Try Again" button that triggers the reset() function to attempt a re-render.

Logging Errors ​

Unexpected errors are logged to the console in development. For production, these can be hooked into monitoring services like Sentry to track recurring issues.

3. Validation Errors ​

Validation ensures that the data sent to the backend is correct and matches the expected schema.

Client-Side Validation ​

We use React Hook Form to manage form state and provide real-time validation feedback. This is used extensively in checkout and customer registration.

  • Immediate Feedback: Errors are displayed as soon as a field loses focus or the form is submitted.
  • Rules: We define rules for required fields, email formats, and minimum lengths.

Server-Side Validation ​

Even with client-side checks, the Bagisto API performs its own validation. If a mutation fails due to business logic (e.g., "Out of stock" or "Invalid address"), the error message is intercepted and displayed to the user via Toasts.

4. Timeout & Retry Logic ​

While not globally enforced, critical operations like cart synchronization and payment capturing can implement retry logic using @tanstack/react-query settings to handle temporary network blips.

typescript
const { data } = useQuery({
  queryKey: ['cart'],
  queryFn: fetchCart,
  retry: 3, // Automatically retry 3 times on failure
  retryDelay: 1000,
});

Best Practices ​

  • Never Show Raw Errors: Avoid displaying technical stack traces or raw GraphQL error objects to users. Always map these to readable messages.
  • Graceful Fallbacks: Use Skeletons or Fallback components when data is missing or fetching fails.
  • Persistent Notifications: Use the ToastProvider for non-blocking notifications that let the user know their action failed without taking them away from their current page.

Next Steps ​

Released under the MIT License.