# Errors

> Every error the runtime throws, what it carries, when it happens, and how to handle it.

Section: Guides · HTML: https://jevascript.org/docs/errors · Markdown: https://jevascript.org/docs/errors.md

All errors extend `SemanticError`, which extends `Error`. Catch the base class to mean "the semantic layer failed", or a subclass to mean something specific.

## The hierarchy

| Class | Type | Default | Description |
| --- | --- | --- | --- |
| `SemanticError` | `extends Error` | — | Base class. Every error below is an instance of it. |
| `NotConfiguredError` | `extends SemanticError` | — | No provider is configured and `JEV_API_KEY` is not set. Thrown on the first call, before any network. |
| `UnsupportedByProviderError` | `extends SemanticError` | — | The provider cannot express the request. Carries `provider` and `feature`. Thrown before any network. |
| `LowConfidenceError` | `extends SemanticError` | — | Measured confidence is below `minConfidence` and no `fallback` was given. Carries `confidence`, `minConfidence` and the `value` that would have been returned. |
| `ProviderError` | `extends SemanticError` | — | Transport or upstream failure after retries are exhausted, a missing API key, or a malformed response. Carries `status` when there was an HTTP status. |
| `SemanticValidationError` | `extends SemanticError` | — | Reserved for semantic validation (`semanticAssert`), which is not built yet. Exported so code can reference it, never thrown today. |

## When each happens

| Situation | Error |
|---|---|
| First call, nothing configured, no key | `NotConfiguredError` |
| `choose()` with more options than the provider allows, or fewer than 2 | `UnsupportedByProviderError` |
| `score()` with `levels` outside the provider's range | `UnsupportedByProviderError` |
| `jev()` has no key at request time | `ProviderError` |
| HTTP 4xx that is not retryable | `ProviderError` with `status` |
| Retryable failures exhausted `maxRetries` | `ProviderError` with the last `status` |
| Timeout | `ProviderError` (the underlying `AbortError` is in the message) |
| Provider returned no answer for a key | `ProviderError` |
| Unstable answer, `minConfidence` set, no `fallback` | `LowConfidenceError` |
| Invalid cache TTL string | plain `Error` at call time |
| `evaluate()` with an empty output | plain `Error` at call time |

## Handling patterns

### Fail open for review, fail closed for action

```ts
import { SemanticError, LowConfidenceError } from "jevascript"

async function grade(ticket) {
  try {
    return await triage(ticket)
  } catch (error) {
    if (error instanceof SemanticError) {
      log.warn("triage.degraded", { reason: String(error) })
      return keywordFallback(ticket)      // support does not stop because a model is down
    }
    throw error                           // anything else is a bug
  }
}

async function canAutoReply(ticket) {
  if (ticket.priority === "critical") return false
  try {
    return await safeToAutoReply(ticket)
  } catch {
    return false                          // when in doubt, a human answers
  }
}
```

### Prefer `fallback` over catching `LowConfidenceError`

```ts
// Instead of try/catch around LowConfidenceError…
const risk = await semantic(order).score("This order is fraudulent.", {
  asProposition: true,
  minConfidence: 0.9,
  fallback: async () => reviewer.assess(order),
})
```

The error is for the case where there is no sensible fallback and the caller must know.

### Distinguish "unavailable" from "wrong"

```ts
} catch (error) {
  if (error instanceof ProviderError && error.status === 429) return retryLater()
  if (error instanceof ProviderError) return degrade()
  if (error instanceof UnsupportedByProviderError) throw error   // a programming error: fix the question
}
```

### Errors inside a batch

If the request behind a `batch()` fails, every promise in that batch rejects with the same error. `Promise.all` therefore rejects once; `Promise.allSettled` shows the same error under each key.

## Where errors are thrown

- **Before the network**: `NotConfiguredError`, `UnsupportedByProviderError`, TTL and empty-output errors. These are programming errors and should surface in development.
- **On the network**: `ProviderError`. These are operational and should be handled.
- **After the answer**: `LowConfidenceError`. This is a policy outcome and should have a fallback.
