# Errors (https://dimah-s3.vercel.app/docs/server/errors)



All failed requests return JSON `{ message, code?, params? }` and standard HTTP status codes.

Use the `errors` helper to throw standard library errors:

```ts
import { APIError, errors, isAPIError, isS3ErrorCode } from "@dimah-s3/server";

// Standard helpers
throw errors.unauthorized();
throw errors.forbidden();
throw errors.objectNotFound();
throw errors.payloadTooLarge();
throw errors.featureDisabled("download");
throw errors.unknownRoute("avatar");
throw errors.fileTypeNotAllowed("application/zip");

// Custom APIError
throw new APIError("BAD_REQUEST", {
  message: "Invalid file payload.",
});
```

Catch and inspect errors:

```ts
if (isAPIError(err)) {
  console.log(err.status, err.statusCode, err.code, err.message);
}

if (isS3ErrorCode(err, "OBJECT_NOT_FOUND")) {
  // Handle missing object specifically
}
```

***

## Error catalog [#error-catalog]

| `code`                   | HTTP | Trigger                                                                        |
| ------------------------ | ---- | ------------------------------------------------------------------------------ |
| `NOT_FOUND`              | 404  | Unknown API path                                                               |
| `UNKNOWN_ROUTE`          | 404  | Target `route` is not registered on the server (`params.route`)                |
| `FEATURE_DISABLED`       | 404  | Target operation (`upload`, `download`, `delete`) is not enabled on this route |
| `OBJECT_NOT_FOUND`       | 404  | Object key or multipart upload does not exist                                  |
| `UNAUTHORIZED`           | 401  | Thrown by your auth guards (`errors.unauthorized()`)                           |
| `FORBIDDEN`              | 403  | Guard rejection or generic unhandled `Error` inside guards                     |
| `CONFLICT`               | 409  | Resource conflict in lifecycle hooks                                           |
| `PAYLOAD_TOO_LARGE`      | 413  | File size exceeds route `maxFileSize` (at presign, part upload, or HeadObject) |
| `FILE_TYPE_NOT_ALLOWED`  | 400  | File type not allowed by route `fileTypes`                                     |
| `VALIDATION_ERROR`       | 400  | Invalid payload shape or malformed checksum                                    |
| `INVALID_KEY`            | 400  | Unsafe key or key outside route `keyPrefix`                                    |
| `MULTIPART_PART_MISSING` | 400  | Complete payload references missing part numbers                               |
| `S3_NETWORK_ERROR`       | 502  | S3 storage service unreachable                                                 |
| `INTERNAL_ERROR`         | 500  | Unhandled server exception or failed `on*` hook                                |

## Frequently asked questions [#frequently-asked-questions]

<Accordions>
  <Accordion title="How do I display friendly error messages on the client?">
    Use `useFormatDimahError` from `@dimah-s3/react` to map error codes to localized user-facing strings:

    ```tsx
    import { isAPIError, useFormatDimahError } from "@dimah-s3/react";

    const formatError = useFormatDimahError();

    try {
      await download(key);
    } catch (err) {
      if (isAPIError(err)) {
        toast.error(formatError(err));
      }
    }
    ```
  </Accordion>
</Accordions>
