Skip to content
// EFFECT DAYS 2026

HttpApiError unstable

Built-in error schemas for common HTTP API failure responses.

This module provides reusable Schema.Error values for common HTTP status codes, plus HttpApiSchemaError for request decoding failures raised by the HTTP API runtime. The status errors can be used in endpoint or middleware error declarations and are understood by builders, generated clients, reflection, and OpenAPI generation.

41 exports Since v4.0.0 Source

Constructors

Problem

unstable
Since v4.0.6

Declares a typed RFC 9457 problem as a yieldable error class.

Details

The class is a Schema.Error whose _tag is the given tag, so Effect.catchTag works without _tag on the wire. It carries the httpApiStatus and application/problem+json annotations, so endpoints that declare it as an error render, document and decode it as a problem. Problem classes that share a status are told apart by type. The extension fields are validated on both sides and cannot replace type, status or title; unknown extensions are not kept. An undeclared instance still renders as a problem through HttpServerRespondable.

Signature

declare function Problem<Self = never, Brand = {}>(): <Tag extends string, Type extends string, Status extends number, Fields extends ProblemExtensionFields = {}>(tag: Tag, declaration: ProblemDeclaration<Type, Status>, fields?: Fields, annotations?: Declaration<Self, readonly [Struct<{ [K in string | number | symbol]: Omit<ProblemMembers<Type, Status>, keyof Fields> & Fields[K] }>]>) => [Self] extends [never] ? "Missing `Self` generic - use `class Self extends HttpApiError.Problem<Self>()(...)`" : ProblemClass<Self, Tag, Type, Status, Fields, Brand>

Example Declaring and using a typed problem

import { Effect, Schema } from "effect"
import { HttpApiEndpoint, HttpApiError } from "effect/http-api"
class OutOfCredit extends HttpApiError.Problem<OutOfCredit>()("OutOfCredit", {
type: "https://example.com/probs/out-of-credit",
status: 403,
title: "You do not have enough credit."
}, {
balance: Schema.Number
}) {}
const buy = HttpApiEndpoint.post("buy", "/buy", { error: OutOfCredit })
const failing = Effect.fail(new OutOfCredit({ balance: 30 }))
// Responds with 403 and { "type": "https://example.com/probs/out-of-credit",
// "status": 403, "title": "You do not have enough credit.", "balance": 30 }

Errors

BadRequest

unstable
Since v4.0.0

Built-in HTTP API error for a 400 Bad Request response. When used directly as a server response, it renders as an empty response with status 400.

Signature

declare class BadRequest extends {
readonly _tag: "BadRequest";
} & YieldableError<this> {
constructor(...args: [props?: {
readonly _tag?: "BadRequest";
}, options?: MakeOptions]);
readonly "~effect/ErrorReporter/ignore": true;
static readonly singleton: BadRequest;
"~effect/http/HttpServerRespondable"(): Effect<HttpServerResponse, never, never>;
}
Since v4.0.6

The problem rendered by HttpApiMiddleware.layerProblemDetails when a request fails decoding.

Details

The body is generic by default. errors is only filled when the layer is built with includeDetails: true.

Signature

declare class BadRequestProblem extends {
readonly detail?: string;
readonly errors?: readonly Array<{
readonly message: string;
readonly path: readonly Array<string | number>;
}>;
readonly instance?: string;
readonly status: 400;
readonly title: string;
readonly type: "about:blank";
} & YieldableError<this> & Respondable & {
readonly _tag: "BadRequestProblem";
} {
constructor(...args: [props?: {
readonly detail?: string;
readonly errors?: readonly Array<{
readonly message: string;
readonly path: readonly Array<string | number>;
}>;
readonly instance?: string;
readonly status?: 400;
readonly title?: string;
readonly type?: "about:blank";
}, options?: MakeOptions]);
}

Conflict

unstable
Since v4.0.0

Built-in HTTP API error for a 409 Conflict response. When used directly as a server response, it renders as an empty response with status 409.

Signature

declare class Conflict extends {
readonly _tag: "Conflict";
} & YieldableError<this> {
constructor(...args: [props?: {
readonly _tag?: "Conflict";
}, options?: MakeOptions]);
readonly "~effect/ErrorReporter/ignore": true;
"~effect/http/HttpServerRespondable"(): Effect<HttpServerResponse, never, never>;
}

Forbidden

unstable
Since v4.0.0

Built-in HTTP API error for a 403 Forbidden response. When used directly as a server response, it renders as an empty response with status 403.

Signature

declare class Forbidden extends {
readonly _tag: "Forbidden";
} & YieldableError<this> {
constructor(...args: [props?: {
readonly _tag?: "Forbidden";
}, options?: MakeOptions]);
readonly "~effect/ErrorReporter/ignore": true;
"~effect/http/HttpServerRespondable"(): Effect<HttpServerResponse, never, never>;
}

Gone

unstable
Since v4.0.0

Built-in HTTP API error for a 410 Gone response. When used directly as a server response, it renders as an empty response with status 410.

Signature

declare class Gone extends {
readonly _tag: "Gone";
} & YieldableError<this> {
constructor(...args: [props?: {
readonly _tag?: "Gone";
}, options?: MakeOptions]);
readonly "~effect/ErrorReporter/ignore": true;
"~effect/http/HttpServerRespondable"(): Effect<HttpServerResponse, never, never>;
}

Error raised when a streaming request payload exceeds a limit declared on its HttpApiSchema.StreamUint8Array or HttpApiSchema.StreamNdjson schema. It responds with an empty 413 Payload Too Large and is ignored by error reporters.

Details

limit names the option that was exceeded: maxBytes caps the whole body and maxElementBytes caps one NDJSON line. size is its configured value.

Signature

declare class HttpApiPayloadTooLarge extends Readonly<{
readonly limit: "maxBytes" | "maxElementBytes";
readonly size: ByteSize;
}> & {
readonly _tag: "HttpApiPayloadTooLarge";
} & Pipeable {
constructor(args: {
readonly limit: "maxBytes" | "maxElementBytes";
readonly size: ByteSize;
});
readonly "~effect/ErrorReporter/ignore": true;
readonly "~effect/http-api/HttpApiError/HttpApiPayloadTooLarge": "~effect/http-api/HttpApiError/HttpApiPayloadTooLarge";
readonly message: string;
readonly name: "HttpApiPayloadTooLarge";
"~effect/http/HttpServerRespondable"(): Effect<HttpServerResponse, never, never>;
static is(u: unknown): u is HttpApiPayloadTooLarge;
}
Since v4.0.0

Error raised when an HTTP API request or response component fails schema decoding or encoding. Request decoding failures respond with an empty 400 Bad Request and are ignored by error reporters. Response encoding failures respond with an empty 500 Internal Server Error and are reported.

Signature

declare class HttpApiSchemaError extends Readonly<{
readonly cause: SchemaError;
readonly kind: "Params" | "Headers" | "Query" | "Body" | "Payload" | "ResponseHeaders";
}> & {
readonly _tag: "HttpApiSchemaError";
} & Pipeable {
constructor(args: {
readonly cause: SchemaError;
readonly kind: "Params" | "Headers" | "Query" | "Body" | "Payload" | "ResponseHeaders";
});
readonly "~effect/http-api/HttpApiError/HttpApiSchemaError": "~effect/http-api/HttpApiError/HttpApiSchemaError";
readonly message: "Params" | "Headers" | "Query" | "Body" | "Payload" | "ResponseHeaders";
readonly name: "HttpApiSchemaError";
"~effect/ErrorReporter/ignore": boolean;
"~effect/http/HttpServerRespondable"(): Effect<HttpServerResponse, never, never>;
static is(u: unknown): u is HttpApiSchemaError;
static wrap<A, R>(kind: "Params" | "Headers" | "Query" | "Body" | "Payload" | "ResponseHeaders", effect: Effect<A, SchemaError, R>): Effect<A, HttpApiSchemaError, R>;
}
Since v4.0.0

Built-in HTTP API error for a 500 Internal Server Error response. When used directly as a server response, it renders as an empty response with status 500.

Signature

declare class InternalServerError extends {
readonly _tag: "InternalServerError";
} & YieldableError<this> {
constructor(...args: [props?: {
readonly _tag?: "InternalServerError";
}, options?: MakeOptions]);
"~effect/http/HttpServerRespondable"(): Effect<HttpServerResponse, never, never>;
}

The problem rendered by HttpApiMiddleware.layerProblemDetails when a response fails encoding.

Signature

declare class InternalServerErrorProblem extends {
readonly detail?: string;
readonly instance?: string;
readonly status: 500;
readonly title: string;
readonly type: "about:blank";
} & YieldableError<this> & Respondable & {
readonly _tag: "InternalServerErrorProblem";
} {
constructor(...args: [props?: {
readonly detail?: string;
readonly instance?: string;
readonly status?: 500;
readonly title?: string;
readonly type?: "about:blank";
}, options?: MakeOptions]);
}
Since v4.0.0

Built-in HTTP API error for a 405 Method Not Allowed response. When used directly as a server response, it renders as an empty response with status 405.

Signature

declare class MethodNotAllowed extends {
readonly _tag: "MethodNotAllowed";
} & YieldableError<this> {
constructor(...args: [props?: {
readonly _tag?: "MethodNotAllowed";
}, options?: MakeOptions]);
readonly "~effect/ErrorReporter/ignore": true;
"~effect/http/HttpServerRespondable"(): Effect<HttpServerResponse, never, never>;
}
Since v4.0.0

Built-in HTTP API error for a 406 Not Acceptable response. When used directly as a server response, it renders as an empty response with status 406.

Signature

declare class NotAcceptable extends {
readonly _tag: "NotAcceptable";
} & YieldableError<this> {
constructor(...args: [props?: {
readonly _tag?: "NotAcceptable";
}, options?: MakeOptions]);
readonly "~effect/ErrorReporter/ignore": true;
"~effect/http/HttpServerRespondable"(): Effect<HttpServerResponse, never, never>;
}

NotFound

unstable
Since v4.0.0

Built-in HTTP API error for a 404 Not Found response. When used directly as a server response, it renders as an empty response with status 404.

Signature

declare class NotFound extends {
readonly _tag: "NotFound";
} & YieldableError<this> {
constructor(...args: [props?: {
readonly _tag?: "NotFound";
}, options?: MakeOptions]);
readonly "~effect/ErrorReporter/ignore": true;
"~effect/http/HttpServerRespondable"(): Effect<HttpServerResponse, never, never>;
}
Since v4.0.0

Built-in HTTP API error for a 501 Not Implemented response. When used directly as a server response, it renders as an empty response with status 501.

Signature

declare class NotImplemented extends {
readonly _tag: "NotImplemented";
} & YieldableError<this> {
constructor(...args: [props?: {
readonly _tag?: "NotImplemented";
}, options?: MakeOptions]);
"~effect/http/HttpServerRespondable"(): Effect<HttpServerResponse, never, never>;
}
Since v4.0.0

Built-in HTTP API error for a 408 Request Timeout response. When used directly as a server response, it renders as an empty response with status 408.

Signature

declare class RequestTimeout extends {
readonly _tag: "RequestTimeout";
} & YieldableError<this> {
constructor(...args: [props?: {
readonly _tag?: "RequestTimeout";
}, options?: MakeOptions]);
readonly "~effect/ErrorReporter/ignore": true;
"~effect/http/HttpServerRespondable"(): Effect<HttpServerResponse, never, never>;
}
Since v4.0.0

Built-in HTTP API error for a 503 Service Unavailable response. When used directly as a server response, it renders as an empty response with status 503.

Signature

declare class ServiceUnavailable extends {
readonly _tag: "ServiceUnavailable";
} & YieldableError<this> {
constructor(...args: [props?: {
readonly _tag?: "ServiceUnavailable";
}, options?: MakeOptions]);
"~effect/http/HttpServerRespondable"(): Effect<HttpServerResponse, never, never>;
}
Since v4.0.0

Built-in HTTP API error for a 401 Unauthorized response. When used directly as a server response, it renders as an empty response with status 401.

Signature

declare class Unauthorized extends {
readonly _tag: "Unauthorized";
} & YieldableError<this> {
constructor(...args: [props?: {
readonly _tag?: "Unauthorized";
}, options?: MakeOptions]);
readonly "~effect/ErrorReporter/ignore": true;
"~effect/http/HttpServerRespondable"(): Effect<HttpServerResponse, never, never>;
}
Since v4.0.0

Built-in HTTP API error for a 422 Unprocessable Entity response. When used directly as a server response, it renders as an empty response with status 422.

Signature

declare class UnprocessableEntity extends {
readonly _tag: "UnprocessableEntity";
} & YieldableError<this> {
constructor(...args: [props?: {
readonly _tag?: "UnprocessableEntity";
}, options?: MakeOptions]);
readonly "~effect/ErrorReporter/ignore": true;
"~effect/http/HttpServerRespondable"(): Effect<HttpServerResponse, never, never>;
}

Models

ProblemClass

interface unstable
Since v4.0.6

The class returned by Problem.

Signature

interface ProblemClass<Self, Tag extends string, Type extends string, Status extends number, Fields extends Schema.Struct.Fields, Brand> extends Class<Self, Schema.Struct<ProblemFields<Type, Status, Fields>>, Cause.YieldableError & HttpServerRespondable.Respondable & Brand & {
readonly _tag: Tag;
}> {
constructor(...args: {} extends MakeInView<{ [K in string | number | symbol]: Omit<ProblemMembers<Type, Status>, keyof Fields> & Fields[K] }, TypeOptionalKeys<{ [K in string | number | symbol]: Omit<ProblemMembers<Type, Status>, keyof Fields> & Fields[K] }> | TypeConstructorDefaultedKeys<{ [K in string | number | symbol]: Omit<ProblemMembers<Type, Status>, keyof Fields> & Fields[K] }>> ? [props?: MakeInView<{ [K in string | number | symbol]: Omit<ProblemMembers<Type, Status>, keyof Fields> & Fields[K] }, TypeOptionalKeys<{ [K in string | number | symbol]: Omit<ProblemMembers<..., ...>, keyof ...> & Fields[K] }> | TypeConstructorDefaultedKeys<{ [K in string | number | symbol]: Omit<ProblemMembers<..., ...>, keyof ...> & Fields[K] }>>, options?: MakeOptions] : [props: MakeInView<{ [K in string | number | symbol]: Omit<ProblemMembers<Type, Status>, keyof Fields> & Fields[K] }, TypeOptionalKeys<{ [K in string | number | symbol]: Omit<ProblemMembers<Type, Status>, keyof Fields> & Fields[K] }> | TypeConstructorDefaultedKeys<{ [K in string | number | symbol]: Omit<ProblemMembers<Type, Status>, keyof Fields> & Fields[K] }>>, options?: MakeOptions]);
}

ProblemDeclaration

interface unstable
Since v4.0.6

The constant members of a typed problem declaration.

Signature

interface ProblemDeclaration<Type extends string, Status extends number> {
readonly status: Status;
readonly title: string;
readonly type: Type;
}
Since v4.0.6

The extension fields a typed problem may declare. The fixed members type, status and title are reserved.

Signature

type ProblemExtensionFields = Schema.Struct.Fields & {
readonly status?: never;
readonly title?: never;
readonly type?: never;
}

ProblemFields

type unstable
Since v4.0.6

The fields of a typed problem class: the standard members plus the declared extension fields.

Signature

type ProblemFields<Type extends string, Status extends number, Fields extends Schema.Struct.Fields> = Simplify<Omit<ProblemMembers<Type, Status>, keyof Fields> & Fields>

ProblemMembers

interface unstable
Since v4.0.6

The standard problem members of a typed problem class.

Details

type, status and title are fixed by the declaration and are constructor defaults that are always encoded. type is the discriminator: a body with a different type is rejected. status and title decode to the declared value whatever the body carries, so the HTTP status stays authoritative. detail and instance are optional per-instance members that declared fields may replace.

Signature

interface ProblemMembers<Type extends string, Status extends number> {
readonly detail: OptionalMember<String>;
readonly instance: OptionalMember<String>;
readonly status: FixedMember<Status>;
readonly title: FixedMember<string>;
readonly type: tag<Type>;
}

Schemas

Since v4.0.0

No-content schema variant for BadRequest, decoding an empty 400 response into a BadRequest error value.

Signature

declare const BadRequestNoContent: asNoContent<typeof BadRequest>
Since v4.0.0

No-content schema variant for Conflict, decoding an empty 409 response into a Conflict error value.

Signature

declare const ConflictNoContent: asNoContent<typeof Conflict>
Since v4.0.0

No-content schema variant for Forbidden, decoding an empty 403 response into a Forbidden error value.

Signature

declare const ForbiddenNoContent: asNoContent<typeof Forbidden>
Since v4.0.0

No-content schema variant for Gone, decoding an empty 410 response into a Gone error value.

Signature

declare const GoneNoContent: asNoContent<typeof Gone>

No-content schema variant for InternalServerError, decoding an empty 500 response into an InternalServerError error value.

Signature

declare const InternalServerErrorNoContent: asNoContent<typeof InternalServerError>

No-content schema variant for MethodNotAllowed, decoding an empty 405 response into a MethodNotAllowed error value.

Signature

declare const MethodNotAllowedNoContent: asNoContent<typeof MethodNotAllowed>

No-content schema variant for NotAcceptable, decoding an empty 406 response into a NotAcceptable error value.

Signature

declare const NotAcceptableNoContent: asNoContent<typeof NotAcceptable>
Since v4.0.0

No-content schema variant for NotFound, decoding an empty 404 response into a NotFound error value.

Signature

declare const NotFoundNoContent: asNoContent<typeof NotFound>

No-content schema variant for NotImplemented, decoding an empty 501 response into a NotImplemented error value.

Signature

declare const NotImplementedNoContent: asNoContent<typeof NotImplemented>
Since v4.0.6

One entry of BadRequestProblem.errors: the location of a request value that failed decoding and the reason.

Details

The first path segment names the request slot (params, headers, query or payload).

Signature

declare const ProblemIssue: Struct<{
readonly message: String;
readonly path: $Array<Union<readonly [String, Number]>>;
}>

No-content schema variant for RequestTimeout, decoding an empty 408 response into a RequestTimeout error value.

Signature

declare const RequestTimeoutNoContent: asNoContent<typeof RequestTimeout>

No-content schema variant for ServiceUnavailable, decoding an empty 503 response into a ServiceUnavailable error value.

Signature

declare const ServiceUnavailableNoContent: asNoContent<typeof ServiceUnavailable>
Since v4.0.0

No-content schema variant for Unauthorized, decoding an empty 401 response into an Unauthorized error value.

Signature

declare const UnauthorizedNoContent: asNoContent<typeof Unauthorized>

No-content schema variant for UnprocessableEntity, decoding an empty 422 response into an UnprocessableEntity error value.

Signature

declare const UnprocessableEntityNoContent: asNoContent<typeof UnprocessableEntity>

Type IDs

Runtime identifier used to mark and detect HttpApiPayloadTooLarge values.

Signature

declare const HttpApiPayloadTooLargeTypeId: "~effect/http-api/HttpApiError/HttpApiPayloadTooLarge"
Since v4.0.6

Type-level identifier used to mark HttpApiPayloadTooLarge values.

Signature

type HttpApiPayloadTooLargeTypeId = "~effect/http-api/HttpApiError/HttpApiPayloadTooLarge"

Runtime identifier used to mark and detect HttpApiSchemaError values.

Signature

declare const HttpApiSchemaErrorTypeId: "~effect/http-api/HttpApiError/HttpApiSchemaError"
Since v4.0.0

Type-level identifier used to mark HttpApiSchemaError values.

Signature

type HttpApiSchemaErrorTypeId = "~effect/http-api/HttpApiError/HttpApiSchemaError"