---
title: "Auth Errors"
description: "Errors for authentication failures, session issues, and authorization requirements."
icon: "lock"
keywords: ['frontmcp', 'mcp', 'model context protocol', 'sdk', 'reference', 'api', 'errors', 'exceptions', 'error handling', 'auth', 'typescript']
---

## Overview

Auth errors are thrown when authentication or authorization fails at the request level. These are public errors that inform clients about what action is needed (re-authenticate, authorize an app, etc.). For internal auth infrastructure errors, see [Auth Internal Errors](/frontmcp/sdk-reference/errors/auth-internal-errors).

## Error Reference

### UnauthorizedError

Thrown when a request is missing valid credentials.

| Property     | Type      | Value          |
| ------------ | --------- | -------------- |
| `code`       | `string`  | `UNAUTHORIZED` |
| `statusCode` | `number`  | `401`          |
| `isPublic`   | `boolean` | `true`         |

```typescript
new UnauthorizedError(message?: string)
```

**Example:**

```typescript
import { UnauthorizedError } from '@frontmcp/sdk';

throw new UnauthorizedError('Bearer token expired');
```

---

### AuthConfigurationError

Thrown when the authentication configuration is invalid (e.g., transparent mode on a parent with multiple child providers).

| Property     | Type                  | Value                        |
| ------------ | --------------------- | ---------------------------- |
| `code`       | `string`              | `AUTH_CONFIGURATION_ERROR`   |
| `statusCode` | `number`              | `500`                        |
| `isPublic`   | `boolean`             | `true`                       |
| `errors`     | `string[]`            | List of configuration errors |
| `suggestion` | `string \| undefined` | How to fix the issue         |

```typescript
new AuthConfigurationError(message: string, options?: {
  errors?: string[];
  suggestion?: string;
})
```

**Example:**

```typescript
import { AuthConfigurationError } from '@frontmcp/sdk';

throw new AuthConfigurationError('Invalid auth configuration', {
  errors: ['Transparent mode requires exactly one child provider'],
  suggestion: 'Set auth.mode to "local" or "remote" when using multiple providers.',
});
```

---

### SessionMissingError

Thrown when a request arrives without a valid session. This tells the client it needs to authenticate.

| Property     | Type      | Value             |
| ------------ | --------- | ----------------- |
| `code`       | `string`  | `SESSION_MISSING` |
| `statusCode` | `number`  | `401`             |
| `isPublic`   | `boolean` | `true`            |

```typescript
new SessionMissingError(message?: string)
```

**Example:**

```typescript
import { SessionMissingError } from '@frontmcp/sdk';

throw new SessionMissingError();
// "Unauthorized: missing session"
```

---

### UnsupportedClientVersionError

Thrown when a client connects with an unsupported MCP protocol version.

| Property        | Type      | Value                              |
| --------------- | --------- | ---------------------------------- |
| `code`          | `string`  | `UNSUPPORTED_CLIENT_VERSION`       |
| `statusCode`    | `number`  | `400`                              |
| `isPublic`      | `boolean` | `true`                             |
| `clientVersion` | `string`  | The version string from the client |

```typescript
new UnsupportedClientVersionError(version: string)

// Factory method
UnsupportedClientVersionError.fromVersion(version: string)
```

**Example:**

```typescript
import { UnsupportedClientVersionError } from '@frontmcp/sdk';

throw UnsupportedClientVersionError.fromVersion('0.1.0');
```

---

### AuthorizationRequiredError

Thrown when a tool requires app-level authorization the user has not yet granted. Supports progressive/incremental authorization. Behavior depends on session mode:

- **Stateful**: Returns an `auth_url` link for incremental authorization
- **Stateless**: Returns an unauthorized error (user must re-authenticate)

| Property              | Type                        | Value                                 |
| --------------------- | --------------------------- | ------------------------------------- |
| `code`                | `string`                    | `AUTHORIZATION_REQUIRED`              |
| `statusCode`          | `number`                    | `403`                                 |
| `isPublic`            | `boolean`                   | `true`                                |
| `appId`               | `string`                    | App requiring authorization           |
| `toolId`              | `string`                    | Tool that triggered the requirement   |
| `authUrl`             | `string \| undefined`       | Auth URL (stateful mode only)         |
| `requiredScopes`      | `string[] \| undefined`     | Scopes needed                         |
| `sessionMode`         | `'stateful' \| 'stateless'` | Session mode                          |
| `supportsIncremental` | `boolean`                   | Whether incremental auth is available |
| `elicitId`            | `string \| undefined`       | Elicit flow ID                        |
| `vaultId`             | `string \| undefined`       | Vault ID for stateful sessions        |
| `pendingAuthId`       | `string \| undefined`       | Tracking ID                           |

```typescript
new AuthorizationRequiredError(params: {
  appId: string;
  toolId: string;
  authUrl?: string;
  requiredScopes?: string[];
  message?: string;
  sessionMode?: 'stateful' | 'stateless';
  elicitId?: string;
  vaultId?: string;
  pendingAuthId?: string;
})
```

**Methods:**

| Method                          | Returns                     | Description                                    |
| ------------------------------- | --------------------------- | ---------------------------------------------- |
| `toMcpError()`                  | MCP error with `_meta`      | Includes authorization metadata for AI agents  |
| `toAuthorizationRequiredData()` | `AuthorizationRequiredData` | Structured data object                         |
| `toElicitResponse()`            | `ElicitResponse \| null`    | Elicit response (stateful only)                |
| `canUseIncrementalAuth()`       | `boolean`                   | Whether link-based auth is available           |
| `getUserFacingMessage()`        | `string`                    | Message with auth link or re-auth instructions |

**Example (stateful):**

```typescript
import { AuthorizationRequiredError } from '@frontmcp/sdk';

throw new AuthorizationRequiredError({
  appId: 'slack',
  toolId: 'slack:send_message',
  authUrl: '/oauth/authorize?app=slack',
  sessionMode: 'stateful',
});
```

**Example (stateless):**

```typescript
throw new AuthorizationRequiredError({
  appId: 'slack',
  toolId: 'slack:send_message',
  sessionMode: 'stateless',
});
```

---

### ToolNotAllowedError

Thrown when a tool is not in the active skill session's allowlist. Used by the [Tool Authorization Guard](/frontmcp/authentication/skills-auth#tool-authorization-guard).

| Property | Type | Value |
| -------- | ---- | ----- |
| `code` | `string` | `TOOL_NOT_ALLOWED` |
| `statusCode` | `number` | `400` |
| `isPublic` | `boolean` | `true` |
| `toolName` | `string` | The denied tool name |
| `skillId` | `string \| undefined` | Active skill session ID |
| `reason` | `string` | `not_in_allowlist`, `denied`, `rate_limited`, or `no_active_skill` |
| `allowedTools` | `string[]` | List of allowed tool names |

```typescript
import { ToolNotAllowedError } from '@frontmcp/sdk';
```

---

### ToolApprovalRequiredError

Thrown when a tool requires explicit approval before use within a skill session (approval policy mode).

| Property | Type | Value |
| -------- | ---- | ----- |
| `code` | `string` | `TOOL_APPROVAL_REQUIRED` |
| `statusCode` | `number` | `400` |
| `isPublic` | `boolean` | `true` |
| `toolName` | `string` | Tool requiring approval |
| `skillId` | `string \| undefined` | Active skill session ID |

```typescript
import { ToolApprovalRequiredError } from '@frontmcp/sdk';
```

---

### ToolNotConsentedError

Thrown when [consent](/frontmcp/authentication/consent) is enabled and the token's authorized-tools claim does not include the requested tool — the runtime enforcement of the consent screen. A user who unchecked a tool during authorization cannot invoke it. Distinguished from a missing tool (`-32601`) so clients can prompt the user to re-authorize and select it.

| Property | Type | Value |
| -------- | ---- | ----- |
| `code` | `string` | `TOOL_NOT_CONSENTED` |
| `mcpErrorCode` | `number` | `-32003` (FORBIDDEN) |
| `statusCode` | `number` | `403` |
| `isPublic` | `boolean` | `true` |
| `toolName` | `string` | The withheld tool name |

```typescript
import { ToolNotConsentedError } from '@frontmcp/sdk';

throw new ToolNotConsentedError('deploy_app');
```

The JSON-RPC `data` payload carries `{ tool }`.

---

### ToolCredentialsRequiredError

Thrown by the call-tool flow's credential gate when a tool declares one or more `authProviders` with `required: true` and the credential for at least one of them is not available for the current session. This is the **tool-level** credential gate (distinct from `AuthorizationRequiredError`, which gates at the **app** level): a tool can be reachable yet still miss a per-provider credential. The call aborts before `execute()` runs.

| Property | Type | Value |
| -------- | ---- | ----- |
| `code` | `string` | `TOOL_CREDENTIALS_REQUIRED` |
| `mcpErrorCode` | `number` | `-32001` (UNAUTHORIZED) |
| `statusCode` | `number` | `401` |
| `isPublic` | `boolean` | `true` |
| `toolId` | `string` | Tool that triggered the gate |
| `providers` | `string[]` | Provider id(s) whose credential is required but missing |
| `authUrl` | `string \| undefined` | Framework-signed connect/authorize URL, if resolvable |

```typescript
import { ToolCredentialsRequiredError } from '@frontmcp/sdk';

throw new ToolCredentialsRequiredError({
  toolId: 'deploy_app',
  providers: ['github'],
  authUrl: 'https://.../oauth/connect?token=…',
});
```

The JSON-RPC `data` payload carries `{ tool, providers, authUrl?, auth_url? }` (the connect URL is emitted under both the camelCase and snake_case keys).
