🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@czap/error

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@czap/error

Composable tagged-error algebra: a closed variant coproduct over an open `TaggedError` contract — value AND type, Effect- and throw-compatible (the foundational zero-dep leaf)

latest
Source
npmnpm
Version
0.9.0
Version published
Maintainers
1
Created
Source

@czap/error

The one LiteShip error algebra — a composable, tagged-error coproduct with zero runtime dependencies. Errors are tagged DATA values, not a class hierarchy: each variant is a _tag-discriminated record that is also a real Error (stack trace + instanceof Error), works with both throw and Effect.fail, and is extended by composing, never editing.

Install

pnpm add @czap/error

Zero runtime deps — it pulls in nothing, not even effect. The Effect interop below works because the records are plain _tag failures; bring your own effect only if you already use it.

30 seconds

import { ValidationError, ParseError, hasTag, matchTag } from '@czap/error';

// A variant is a VALUE and a TYPE. Throw it — it's a real Error:
throw ValidationError('Boundary.make', 'width must be > 0');

// Branch on the tag, not `instanceof`. `hasTag` narrows:
if (hasTag(caught, 'ParseError')) report(caught.source, caught.offset);

// `matchTag` is exhaustive over a closed union — add a variant and every
// match site must handle it or it fails to compile:
function explain(err: ValidationError | ParseError): string {
  return matchTag(err, {
    ValidationError: (e) => `rejected by ${e.module}: ${e.detail}`,
    ParseError: (e) => `could not read ${e.source}: ${e.detail}`,
  });
}

The exact same value is a first-class Effect failure — no effect import inside @czap/error, because Effect.catchTag keys on the _tag these records already carry:

import { Effect } from 'effect';

Effect.fail(ParseError('profile.json', 'expected object', { offset: 12 }))
  .pipe(Effect.catchTag('ParseError', (e) => Effect.succeed(e.detail)));

Where it sits

This is the foundational leaf the rest of the stack adopts — standalone, with zero @czap/* dependencies, so any package can fail with it. The built-in variants form one CLOSED coproduct (LiteShipError = ValidationError | ParseError | IoError | HostCapabilityError | InvariantViolationError | NotFoundError | UnsupportedError | IntegrityError) over the open TaggedError contract every helper (hasTag, matchTag, matchTagOr, raise, assertNever) operates on. See the package surfaces map for the full layout.

When a variant doesn't fit

Do not subclass — there is no base class to extend. You compose: conform a record to TaggedError, build it with the one taggedError composer, and widen the union by |. Editing @czap/error is never the extension path.

import { taggedError, type TaggedError, type LiteShipError } from '@czap/error';

interface RateLimitError extends TaggedError<'RateLimitError'> {
  readonly retryAfter: number;
}
const RateLimitError = (retryAfter: number): RateLimitError =>
  taggedError('RateLimitError', `retry after ${retryAfter}s`, { retryAfter });

type AppError = LiteShipError | RateLimitError; // composition over inheritance

Every helper keeps working on the widened union unchanged — matchTagOr handles the variants you care about and routes the rest through a fallback. Zero rebuild, zero fork.

Docs

Part of LiteShip — powered by the CZAP engine (Content-Zoned Adaptive Projection), distributed as @czap/* packages.

Keywords

czap

FAQs

Package last updated on 09 Jul 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts