Documentation

Error Handling

Learn how to handle errors effectively in your API endpoints.

Using ORPCError

The project uses ORPCError for standardized error handling. This ensures consistent error responses across your API.

Basic Usage

import { ORPCError } from "@orpc/server";

export const exampleAction = protectedProcedure
  .route({
    method: "POST",
    path: "/example",
  })
  .handler(async ({ input }) => {
    if (!isValid(input)) {
      throw new ORPCError("BAD_REQUEST", {
        message: "Invalid input data",
      });
    }

    return { success: true };
  });

Error Codes

Standard HTTP Error Codes

oRPC supports standard HTTP error codes:

CodeHTTP StatusDescriptionUse Case
BAD_REQUEST400Invalid requestInput validation failures
UNAUTHORIZED401Not authenticatedMissing or invalid session
FORBIDDEN403No permissionInsufficient permissions
NOT_FOUND404Resource not foundResource doesn't exist
CONFLICT409Resource conflictDuplicate entries
TOO_MANY_REQUESTS429Rate limit exceededToo many requests
INTERNAL_SERVER_ERROR500Server errorUnexpected errors

Common Patterns

Validation Errors

export const createUser = publicProcedure
  .route({
    method: "POST",
    path: "/users",
  })
  .input(userSchema)
  .handler(async ({ input }) => {
    // Check if email already exists
    const existing = await findUserByEmail(input.email);

    if (existing) {
      throw new ORPCError("CONFLICT", {
        message: "Email already registered",
        cause: { field: "email" },
      });
    }

    return await createUser(input);
  });

Resource Not Found

export const getUser = publicProcedure
  .route({
    method: "GET",
    path: "/users/:id",
  })
  .input(z.object({
    id: z.string(),
  }))
  .handler(async ({ input }) => {
    const user = await findUserById(input.id);

    if (!user) {
      throw new ORPCError("NOT_FOUND", {
        message: `User with ID ${input.id} not found`,
      });
    }

    return user;
  });

Error Messages

User-Friendly Messages

Provide clear, actionable error messages:

// Good - Clear and actionable
throw new ORPCError("BAD_REQUEST", {
  message: "Password must be at least 8 characters long",
});

// Bad - Vague and unhelpful
throw new ORPCError("BAD_REQUEST", {
  message: "Invalid input",
});

Including Error Details

Add context to help debugging:

throw new ORPCError("CONFLICT", {
  message: "Username already taken",
  cause: {
    field: "username",
    value: input.username,
    suggestion: "Try adding numbers or your name",
  },
});