---
title: "Errors"
description: "Every error class that forges throws."
canonical_url: "https://forges.link/reference/errors"
---
# Errors

> Every error class that forges throws.

All errors extend [`ForgeError`](#forgeerror). Errors from a request carry `forge`, `instance`, `url` and `method`. A class has the properties of the classes it extends. See [Handle errors and rate limits](https://forges.link/guides/errors).

## `ForgeErrorContext`

Where an error happened: the forge, the instance and the request.

<table>
<thead>
  <tr>
    <th>
      Member
    </th>
    
    <th>
      Type
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        forge?
      </code>
    </td>
    
    <td>
      <a href="https://forges.link/reference/data-model#forgekind">
        <code>
          ForgeKind
        </code>
      </a>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        instance?
      </code>
    </td>
    
    <td>
      <a href="https://forges.link/reference/data-model#forgeinstance">
        <code>
          ForgeInstance
        </code>
      </a>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        url?
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        method?
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
  </tr>
</tbody>
</table>

## `ForgeError`

Base class for every error that forges throws.

**extends:** `Error`

```ts
new ForgeError(message: string, context: ForgeErrorContext = {}, options?: ErrorOptions)
```

<table>
<thead>
  <tr>
    <th>
      Parameter
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        message
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        context?
      </code>
    </td>
    
    <td>
      <a href="https://forges.link/reference/errors#forgeerrorcontext">
        <code>
          ForgeErrorContext
        </code>
      </a>
    </td>
    
    <td>
      Defaults to <code>
        {}
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        options?
      </code>
    </td>
    
    <td>
      <code>
        ErrorOptions
      </code>
    </td>
    
    <td>
      
    </td>
  </tr>
</tbody>
</table>

<table>
<thead>
  <tr>
    <th>
      Member
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        forge?
      </code>
    </td>
    
    <td>
      <a href="https://forges.link/reference/data-model#forgekind">
        <code>
          ForgeKind
        </code>
      </a>
    </td>
    
    <td>
      The forge that the request went to.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        instance?
      </code>
    </td>
    
    <td>
      <a href="https://forges.link/reference/data-model#forgeinstance">
        <code>
          ForgeInstance
        </code>
      </a>
    </td>
    
    <td>
      
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        url?
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        method?
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      
    </td>
  </tr>
</tbody>
</table>

## `ForgeApiError`

The forge responded with an error.

**extends:** [`ForgeError`](https://forges.link/reference/errors#forgeerror)

```ts
new ForgeApiError(message: string, status: number, body: string, context?: ForgeErrorContext, options?: ErrorOptions)
```

<table>
<thead>
  <tr>
    <th>
      Parameter
    </th>
    
    <th>
      Type
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        message
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        status
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        body
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        context?
      </code>
    </td>
    
    <td>
      <a href="https://forges.link/reference/errors#forgeerrorcontext">
        <code>
          ForgeErrorContext
        </code>
      </a>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        options?
      </code>
    </td>
    
    <td>
      <code>
        ErrorOptions
      </code>
    </td>
  </tr>
</tbody>
</table>

<table>
<thead>
  <tr>
    <th>
      Member
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        status
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        body
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      Truncated response body, for diagnostics.
    </td>
  </tr>
</tbody>
</table>

## `NotFoundError`

A 404: the resource does not exist, or the credential cannot see it. Many forges respond the same way to both.

**extends:** [`ForgeApiError`](https://forges.link/reference/errors#forgeapierror)

## `AuthenticationRequiredError`

A 401, or a 403 with a request budget of zero (GitHub GraphQL), for a request
sent without credentials. A rejected credential is [`TokenRevokedError`](https://forges.link/reference/errors#tokenrevokederror).

**extends:** [`ForgeApiError`](https://forges.link/reference/errors#forgeapierror)

## `RateLimitedError`

The forge rate limited the request and a retry didn't help. Every rate limit rejects with this class, primary or secondary.

**extends:** [`ForgeApiError`](https://forges.link/reference/errors#forgeapierror)

```ts
new RateLimitedError(message: string, status: number, body: string, options: { resetAt?: Date, secondary?: boolean } & ForgeErrorContext = {}, errorOptions?: ErrorOptions)
```

<table>
<thead>
  <tr>
    <th>
      Parameter
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        message
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        status
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        body
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        options?
      </code>
    </td>
    
    <td>
      <a href="https://forges.link/reference/errors#forgeerrorcontext">
        <code>
          { resetAt?: Date, secondary?: boolean } & ForgeErrorContext
        </code>
      </a>
    </td>
    
    <td>
      Defaults to <code>
        {}
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        errorOptions?
      </code>
    </td>
    
    <td>
      <code>
        ErrorOptions
      </code>
    </td>
    
    <td>
      
    </td>
  </tr>
</tbody>
</table>

<table>
<thead>
  <tr>
    <th>
      Member
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        resetAt?
      </code>
    </td>
    
    <td>
      <code>
        Date
      </code>
    </td>
    
    <td>
      When to send again: after the forge's <code>
        retry-after
      </code>
      
      , or when a used-up budget resets. Absent when the forge names neither.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        secondary
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      Whether the forge applied a secondary limit, such as a limit on concurrent requests or on content creation, rather than a used-up request budget. No remaining-request counter predicts it.
    </td>
  </tr>
</tbody>
</table>

## `TokenRevokedError`

The credential was revoked or expired.

**extends:** [`ForgeApiError`](https://forges.link/reference/errors#forgeapierror)

## `InsufficientScopeError`

The credential is valid but lacks the scope or permission for this call.

**extends:** [`ForgeApiError`](https://forges.link/reference/errors#forgeapierror)

```ts
new InsufficientScopeError(message: string, status: number, body: string, context?: ForgeErrorContext & Pick<InsufficientScopeError, 'acceptedScopes' | 'grantedScopes' | 'acceptedPermissionsRaw'>, options?: ErrorOptions)
```

<table>
<thead>
  <tr>
    <th>
      Parameter
    </th>
    
    <th>
      Type
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        message
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        status
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        body
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        context?
      </code>
    </td>
    
    <td>
      <code>
        ForgeErrorContext & Pick<InsufficientScopeError, 'acceptedScopes' | 'grantedScopes' | 'acceptedPermissionsRaw'>
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        options?
      </code>
    </td>
    
    <td>
      <code>
        ErrorOptions
      </code>
    </td>
  </tr>
</tbody>
</table>

<table>
<thead>
  <tr>
    <th>
      Member
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        acceptedScopes?
      </code>
    </td>
    
    <td>
      <code>
        string[]
      </code>
    </td>
    
    <td>
      Scopes that would allow the request, any one of them, where the forge names them (GitHub's <code>
        X-Accepted-OAuth-Scopes
      </code>
      
      ).
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        grantedScopes?
      </code>
    </td>
    
    <td>
      <code>
        string[]
      </code>
    </td>
    
    <td>
      Scopes the credential holds, where the forge reports them (GitHub's <code>
        X-OAuth-Scopes
      </code>
      
      ).
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        acceptedPermissionsRaw?
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      Fine-grained permissions that would allow the request, verbatim, such as <code>
        issues=write
      </code>
      
       (GitHub's <code>
        X-Accepted-GitHub-Permissions
      </code>
      
      ).
    </td>
  </tr>
</tbody>
</table>

## `ForbiddenReason`

Why the forge refused a request the credential is otherwise valid for.
`unknown` is a 403 whose body matched nothing recognised.

**one of:**

- `'org_restriction'`
- `'sso_required'`
- `'immutable_release'`
- `'resource_protected'`
- `'unknown'`

## `ForbiddenError`

The forge refused the request for a reason other than a missing scope or a
rate limit: an organisation policy, an SSO requirement, a protected
resource, or a release the forge has marked immutable. A missing scope is
[`InsufficientScopeError`](https://forges.link/reference/errors#insufficientscopeerror), and a rate limit [`RateLimitedError`](https://forges.link/reference/errors#ratelimitederror).

**extends:** [`ForgeApiError`](https://forges.link/reference/errors#forgeapierror)

```ts
new ForbiddenError(message: string, status: number, body: string, reason: ForbiddenReason, context?: ForgeErrorContext & { reasonRaw?: string, ssoUrl?: string }, options?: ErrorOptions)
```

<table>
<thead>
  <tr>
    <th>
      Parameter
    </th>
    
    <th>
      Type
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        message
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        status
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        body
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        reason
      </code>
    </td>
    
    <td>
      <a href="https://forges.link/reference/errors#forbiddenreason">
        <code>
          ForbiddenReason
        </code>
      </a>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        context?
      </code>
    </td>
    
    <td>
      <a href="https://forges.link/reference/errors#forgeerrorcontext">
        <code>
          ForgeErrorContext & { reasonRaw?: string, ssoUrl?: string }
        </code>
      </a>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        options?
      </code>
    </td>
    
    <td>
      <code>
        ErrorOptions
      </code>
    </td>
  </tr>
</tbody>
</table>

<table>
<thead>
  <tr>
    <th>
      Member
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        reason
      </code>
    </td>
    
    <td>
      <a href="https://forges.link/reference/errors#forbiddenreason">
        <code>
          ForbiddenReason
        </code>
      </a>
    </td>
    
    <td>
      Why the forge refused the request.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        reasonRaw?
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      The forge's own wording, for diagnostics and for reasons that have no <code>
        ForbiddenReason
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ssoUrl?
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      Where the user authorises the credential for the organisation, when <code>
        reason
      </code>
      
       is <code>
        sso_required
      </code>
      
       and the forge links it (GitHub's <code>
        X-GitHub-SSO
      </code>
      
      ).
    </td>
  </tr>
</tbody>
</table>

## `ForgeTimeoutError`

A request or a pending merge exceeded `timeout`.

**extends:** [`ForgeError`](https://forges.link/reference/errors#forgeerror)

```ts
new ForgeTimeoutError(message: string, timeout: number, context?: ForgeErrorContext, options?: ErrorOptions)
```

<table>
<thead>
  <tr>
    <th>
      Parameter
    </th>
    
    <th>
      Type
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        message
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        timeout
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        context?
      </code>
    </td>
    
    <td>
      <a href="https://forges.link/reference/errors#forgeerrorcontext">
        <code>
          ForgeErrorContext
        </code>
      </a>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        options?
      </code>
    </td>
    
    <td>
      <code>
        ErrorOptions
      </code>
    </td>
  </tr>
</tbody>
</table>

<table>
<thead>
  <tr>
    <th>
      Member
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        timeout
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      The timeout that was exceeded, in milliseconds.
    </td>
  </tr>
</tbody>
</table>

## `SubscriptionClosedError`

A subscription connection closed or failed. Resume from `cursor`.

**extends:** [`ForgeError`](https://forges.link/reference/errors#forgeerror)

```ts
new SubscriptionClosedError(message: string, cursor: string | undefined, context?: ForgeErrorContext, options?: ErrorOptions)
```

<table>
<thead>
  <tr>
    <th>
      Parameter
    </th>
    
    <th>
      Type
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        message
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        cursor
      </code>
    </td>
    
    <td>
      <code>
        string | undefined
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        context?
      </code>
    </td>
    
    <td>
      <a href="https://forges.link/reference/errors#forgeerrorcontext">
        <code>
          ForgeErrorContext
        </code>
      </a>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        options?
      </code>
    </td>
    
    <td>
      <code>
        ErrorOptions
      </code>
    </td>
  </tr>
</tbody>
</table>

<table>
<thead>
  <tr>
    <th>
      Member
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        cursor?
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      The cursor of the last event received. Pass it to <code>
        subscribe()
      </code>
      
       to resume.
    </td>
  </tr>
</tbody>
</table>

## `ForgeNetworkError`

The request never got a response: DNS, TLS, connection refused or a proxy refusal.

**extends:** [`ForgeError`](https://forges.link/reference/errors#forgeerror)

## `UnsupportedOperationError`

The forge doesn't support the operation.

**extends:** [`ForgeError`](https://forges.link/reference/errors#forgeerror)

## `ReadOnlyError`

A write was called on a provider constructed with `readOnly: true`.

**extends:** [`UnsupportedOperationError`](https://forges.link/reference/errors#unsupportedoperationerror)

## `ContentNotTextError`

`contents.file` was asked for text and the file's bytes are not valid UTF-8.

**extends:** [`ForgeError`](https://forges.link/reference/errors#forgeerror)

## `UnknownForgeError`

A ref names a forge instance no registered provider serves.

**extends:** [`ForgeError`](https://forges.link/reference/errors#forgeerror)

## `UnresolvedThreadError`

The thread ref has no number, or is a kind the provider cannot address.

**extends:** [`ForgeError`](https://forges.link/reference/errors#forgeerror)

These exports are documented elsewhere: [`MergeBlockedError`](https://forges.link/reference/data-model#mergeblockederror), [`MergeConflictError`](https://forges.link/reference/data-model#mergeconflicterror), [`BranchMovedError`](https://forges.link/reference/data-model#branchmovederror), [`WebhookVerificationError`](https://forges.link/reference/data-model#webhookverificationerror), [`MergeMethodRequiredError`](https://forges.link/reference/data-model#mergemethodrequirederror).


## Sitemap

See the full [sitemap](https://forges.link/sitemap.md) for all pages.
