> ## Documentation Index
> Fetch the complete documentation index at: https://inertiajs-vi.tuantq.online/llms.txt
> Use this file to discover all available pages before exploring further.

# Xử lý lỗi

## Môi trường phát triển

Một lợi thế khi làm việc với server-side framework mạnh là bạn được hưởng sẵn cơ chế xử lý exception. Ví dụ, Laravel đi kèm công cụ báo lỗi trực quan, hiển thị stack trace được định dạng rõ ràng trong môi trường phát triển local.

Khó khăn nằm ở chỗ khi bạn thực hiện request XHR (như Inertia vẫn làm) và gặp lỗi phía máy chủ, thông thường bạn phải mở tab Network trong devtools của trình duyệt để lần tìm và chẩn đoán vấn đề.

Inertia giải quyết vấn đề này bằng cách hiển thị mọi response không phải Inertia trong một modal. Nhờ vậy, bạn vẫn có trải nghiệm báo lỗi trực quan quen thuộc dù request được thực hiện qua XHR.

Với ứng dụng dùng [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) hạn chế inline style, bạn có thể truyền `nonce` vào `createInertiaApp()` để cho phép inline style do error modal inject. Xem [Content Security Policy](/v3/installation/client-side-setup#content-security-policy) để biết chi tiết.

## Production

Trong production, bạn nên trả proper Inertia error response thay vì dựa vào error reporting bằng modal vốn dùng trong development. Có thể thực hiện bằng phương thức `Inertia::handleExceptionsUsing()` trong service provider của ứng dụng.

```php theme={null}
// app/Providers/AppServiceProvider.php
use Inertia\Inertia;
use Inertia\ExceptionResponse;

public function boot(): void
{
    Inertia::handleExceptionsUsing(function (ExceptionResponse $response) {
        if (in_array($response->statusCode(), [403, 404, 500, 503])) {
            return $response->render('ErrorPage', [
                'status' => $response->statusCode(),
            ])->withSharedData();
        }
    });
}
```

Vì exception như 404 xảy ra bên ngoài Inertia middleware (request không bao giờ tới route), error response mặc định không truy cập được shared data hoặc root view. Gọi `withSharedData()` rõ ràng sẽ resolve Inertia middleware và đưa shared props vào error page.

Instance `ExceptionResponse` cung cấp `exception`, `request` và `response` dưới dạng public readonly property, cùng các method sau:

* `render($component, $props)` - Render Inertia page component với props được cung cấp
* `withSharedData()` - Bao gồm shared data từ Inertia middleware
* `usingMiddleware($class)` - Chỉ định Inertia middleware dùng để resolve shared data và root view
* `rootView($view)` - Đặt custom root view cho error response
* `statusCode()` - Lấy HTTP status code của response ban đầu

Inertia middleware được tự động resolve từ matched route hoặc middleware group của kernel, nên `withSharedData()` thường hoạt động mà không cần chỉ định middleware class. Trả `null` từ callback sẽ fallback về cách render exception mặc định của Laravel.

### Ví dụ trang lỗi

Bạn cần tạo các error page component được tham chiếu ở trên. Dưới đây là ví dụ có thể dùng làm điểm bắt đầu.

<CodeGroup>
  ```vue Vue icon="vuejs" theme={null}
  <script setup>
  import { computed } from "vue";

  const props = defineProps({ status: Number });

  const title = computed(() => {
    return {
      503: "503: Service Unavailable",
      500: "500: Server Error",
      404: "404: Page Not Found",
      403: "403: Forbidden",
    }[props.status];
  });

  const description = computed(() => {
    return {
      503: "Sorry, we are doing some maintenance. Please check back soon.",
      500: "Whoops, something went wrong on our servers.",
      404: "Sorry, the page you are looking for could not be found.",
      403: "Sorry, you are forbidden from accessing this page.",
    }[props.status];
  });
  </script>

  <template>
    <div>
      <h1>{{ title }}</h1>
      <div>{{ description }}</div>
    </div>
  </template>
  ```

  ```jsx React icon="react" theme={null}
  export default function ErrorPage({ status }) {
    const title = {
      503: "503: Service Unavailable",
      500: "500: Server Error",
      404: "404: Page Not Found",
      403: "403: Forbidden",
    }[status];

    const description = {
      503: "Sorry, we are doing some maintenance. Please check back soon.",
      500: "Whoops, something went wrong on our servers.",
      404: "Sorry, the page you are looking for could not be found.",
      403: "Sorry, you are forbidden from accessing this page.",
    }[status];

    return (
      <div>
        <h1>{title}</h1>
        <div>{description}</div>
      </div>
    );
  }
  ```

  ```svelte Svelte icon="s" theme={null}
  <script>
      let { status } = $props()

      const title = {
          503: '503: Service Unavailable',
          500: '500: Server Error',
          404: '404: Page Not Found',
          403: '403: Forbidden',
      }

      const description = {
          503: 'Sorry, we are doing some maintenance. Please check back soon.',
          500: 'Whoops, something went wrong on our servers.',
          404: 'Sorry, the page you are looking for could not be found.',
          403: 'Sorry, you are forbidden from accessing this page.',
      }
  </script>

  <div>
      <h1>{title[status]}</h1>
      <div>{description[status]}</div>
  </div>
  ```
</CodeGroup>

### Xử lý exception thủ công

Bên dưới, `handleExceptionsUsing()` đăng ký callback `$exceptions->respond()` trong file `bootstrap/app.php` của ứng dụng. Bạn có thể đăng ký callback này thủ công nếu muốn.

```php theme={null}
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
use Inertia\Inertia;

->withExceptions(function (Exceptions $exceptions) {
    $exceptions->respond(function (Response $response, Throwable $exception, Request $request) {
        if (! app()->environment(['local', 'testing']) && in_array($response->getStatusCode(), [500, 503, 404, 403])) {
            return Inertia::render('ErrorPage', ['status' => $response->getStatusCode()])
                ->toResponse($request)
                ->setStatusCode($response->getStatusCode());
        }

        return $response;
    });
})
```

***

## Tài liệu chính thức

Bài dịch này được đối chiếu từ [tài liệu Inertia.js v3 chính thức](https://inertiajs.com/docs/v3/advanced/error-handling). Nếu có khác biệt do phiên bản hoặc cập nhật mới, hãy ưu tiên tài liệu chính thức làm nguồn tham chiếu.
