Skip to main content
The error endpoint retrieves detailed information about errors that occur during self-service flows. When a flow encounters an error, Kratos redirects to your error UI with an error ID, which you can use to fetch the error details.

Get flow error

curl -X GET 'https://your-project.projects.oryapis.com/self-service/errors?id=a3c48c1e-62a0-4a8a-9b3e-1f9c7d5e2b4a' \
  -H 'Content-Type: application/json'
Retrieve the error associated with a user-facing self-service error. This endpoint returns error details that can be displayed to users.

Method and path

GET /self-service/errors

Authentication

No authentication required.

Request parameters

id
string
required
The error’s ID. This is provided in the error query parameter when Kratos redirects to your error UI.For testing, use stub value stub:500 to get a stub Internal Server Error.

Response

id
string
required
ID of the error container
error
object
The error details
created_at
string
When the error was created
updated_at
string
When the error was last updated

Example response

{
  "id": "a3c48c1e-62a0-4a8a-9b3e-1f9c7d5e2b4a",
  "error": {
    "code": 400,
    "status": "Bad Request",
    "message": "The request was malformed or invalid",
    "reason": "The email address provided is already in use",
    "id": "duplicate_credentials",
    "request": "d7ef54b1-ec15-46e6-bccb-524b82c035e6"
  },
  "created_at": "2026-03-03T15:30:00Z",
  "updated_at": "2026-03-03T15:30:00Z"
}

Error responses

403
object
Forbidden - Access denied to this error
404
object
Not Found - Error ID does not exist or has expired
500
object
Internal Server Error

Error flow in self-service

When an error occurs during a self-service flow (login, registration, recovery, verification, or settings), Kratos follows this process:
  1. Error occurs - Something goes wrong during the flow (e.g., validation error, network issue, internal error)
  2. Kratos redirects - Kratos redirects the browser to your configured error UI URL with the error ID:
    https://your-app.com/error?id=a3c48c1e-62a0-4a8a-9b3e-1f9c7d5e2b4a
    
  3. Fetch error details - Your error UI calls this endpoint to get the error details:
    GET /self-service/errors?id=a3c48c1e-62a0-4a8a-9b3e-1f9c7d5e2b4a
    
  4. Display to user - Show the error message to the user in a friendly format

Displaying errors to users

When displaying errors to users, follow these best practices:

Show user-friendly messages

Use the message and reason fields to display helpful information:
const errorData = await fetch(
  `https://your-kratos-url/self-service/errors?id=${errorId}`
).then(r => r.json());

const displayMessage = errorData.error.reason || errorData.error.message;

Handle different error types

Common error scenarios in self-service flows:
Status: 400 Bad RequestCause: Invalid input (e.g., weak password, invalid email format)Action: Display the validation message and allow the user to correct their input
Status: 400 Bad RequestCause: Email or username already existsAction: Inform the user and suggest login or account recovery
Status: 410 GoneCause: The self-service flow took too long and expiredAction: Redirect to start a new flow
Status: 500 Internal Server ErrorCause: Server-side issueAction: Show a generic error message and provide a way to contact support

Example error UI implementation

import { useSearchParams } from 'react-router-dom';
import { useEffect, useState } from 'react';

export function ErrorPage() {
  const [searchParams] = useSearchParams();
  const errorId = searchParams.get('id');
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    if (!errorId) {
      setLoading(false);
      return;
    }

    fetch(`https://your-kratos-url/self-service/errors?id=${errorId}`)
      .then(res => res.json())
      .then(data => {
        setError(data.error);
        setLoading(false);
      })
      .catch(err => {
        console.error('Failed to fetch error:', err);
        setLoading(false);
      });
  }, [errorId]);

  if (loading) {
    return <div>Loading...</div>;
  }

  if (!error) {
    return <div>An unknown error occurred</div>;
  }

  return (
    <div className="error-container">
      <h1>Oops! Something went wrong</h1>
      <p>{error.reason || error.message}</p>
      
      {error.code === 410 && (
        <p>
          This flow has expired. Please <a href="/login">start over</a>.
        </p>
      )}
      
      {error.code >= 500 && (
        <p>
          We're experiencing technical difficulties. Please try again later
          or <a href="/support">contact support</a> with error ID: {error.id}
        </p>
      )}
      
      <button onClick={() => window.history.back()}>
        Go Back
      </button>
    </div>
  );
}

Testing error handling

Kratos provides stub error IDs for testing your error UI:
curl -X GET 'https://your-project.projects.oryapis.com/self-service/errors?id=stub:500' \
  -H 'Content-Type: application/json'
This returns a sample 500 Internal Server Error that you can use to test your error display logic.

Configuration

Configure the error UI URL in your Kratos configuration:
selfservice:
  flows:
    error:
      ui_url: https://your-app.com/error
For more information, see the User-Facing Errors documentation.

Build docs developers (and LLMs) love