RE

result-error-handling

A utility for implementing and managing error handling patterns in brepjs using Result types and custom error codes.

Install

mkdir -p .claude/skills/result-error-handling && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/17444" && unzip -o skill.zip -d .claude/skills/result-error-handling && rm skill.zip

Installs to .claude/skills/result-error-handling

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

This skill should be used when working with Result<T,E>, BrepError, or error paths in brepjs — deciding whether to throw or return a Result, constructing errors with codes, or handling failures. Trigger phrases include "should this throw or return err", "Called unwrap() on an Err", "add a new error code", "BrepErrorCode", "kernelCall", "unsupportedError", "BrepWrapperError", "the operation failed silently", "error was swallowed", "how do I unwrap this Result", or writing a new *Fns.ts function that can fail.
513 chars✓ has a “when” triggerlonger than Claude Code's old 250-char listing cap (fine on current versions)
Intermediate

Key capabilities

  • Return `Result<T, BrepError>` for expected failures in brepjs operations.
  • Throw `BrepBugError` for programmer bugs or broken invariants.
  • Throw `BrepWrapperError` when unwrapping an `Err` from the `shape()` facade.
  • Construct errors using `kernelCall` for kernel operations.
  • Manually construct `BrepError` objects with specific kinds and codes.
  • Translate cryptic OCCT messages into actionable text with `translateKernelError()`.

How it works

The skill guides the selection of failure channels, either returning a `Result` for expected failures or throwing an exception for programmer bugs. It provides helpers like `kernelCall` to construct errors with translated messages and suggestions.

Inputs & outputs

You give it
A fallible operation in brepjs
You get back
A `Result<T, BrepError>` indicating success or failure

When to use result-error-handling

  • Deciding whether to throw or return an error
  • Constructing new error codes
  • Handling operation failures
  • Unwrapping result types

About this skill

Result types and error handling

Every fallible operation in brepjs returns Result<T, BrepError> instead of throwing. The type, all combinators, and the extraction helpers live in src/core/result.ts (zero internal imports — a pure foundation module). Error kinds, the code catalog, and per-kind constructors live in src/core/errors.ts.

The two failure channels

Pick the channel before writing any error-handling code:

SituationChannelMechanism
Expected failure (bad input, kernel op failed, unsupported capability, file won't parse)Resulterr(validationError(...)), kernelCall(...), etc.
Programmer bug / broken invariant ("this can never happen")Throwbug(location, message) from src/utils/bug.ts — throws BrepBugError, never meant to be caught
Out-of-bounds index that is valid by construction (under noUncheckedIndexedAccess)ThrowsafeIndex(arr, i, context) in src/core/errors.ts — the sanctioned arr[i]! replacement
Cooperative cancellationThrowif (signal?.aborted) throw signal.reason (see src/topology/booleanFns.ts)

The rule for Layers 2–3 (.claude/commands/new-operation.md, CLAUDE.md): never throw for expected failures — return ok(...) or err(...). No ESLint rule enforces this mechanically, so it must be applied by discipline in every new *Fns.ts function. The exceptions above (bug(), safeIndex(), abort rethrows) are the only tolerated throws.

The one sanctioned Result→throw boundary is the fluent shape() facade in src/topology/wrapperFns.ts: every chainable method funnels through an internal unwrapOrThrow that throws BrepWrapperError on Err. See "The throwing boundary" below.

Constructing errors

Prefer kernelCall for kernel operations

src/core/kernelCall.ts is the standard error-construction path in *Fns.ts files. It wraps try/catch, casts the result, translates cryptic OCCT messages, and auto-attaches a suggestion:

// src/topology/shapeFns.ts
return kernelCall(
  () => getKernel().downcast(shape.wrapped),
  BrepErrorCode.CLONE_FAILED,
  'Failed to clone shape'
) as Result<T>;

Three variants:

HelperReturnsUse when
kernelCall(fn, code, message, kind?)Result<AnyShape>Kernel call returns a KernelShape; auto-runs castShape()
kernelCallRaw<T>(fn, code, message, kind?)Result<T>Kernel call returns anything else (string, number, array)
kernelCallScoped(fn, code, message, kind?)Result<AnyShape>fn(scope) needs intermediate kernel allocations — the DisposalScope is disposed even on the error path (see the memory-and-disposal skill)

On exception, the error message becomes `${message}: ${translated}` where translateKernelError() (src/core/kernelErrorTranslation.ts) maps ~12 cryptic OCCT patterns (BRepAlgoAPI failures, fillet radius too large, degenerate geometry, ...) into actionable text with the original appended as (kernel: ...). Translation applies only when kind is 'KERNEL_OPERATION' (the default). ERROR_CODE_SUGGESTIONS in the same file maps a dozen codes (FUSE_FAILED, CUT_FAILED, *_NOT_3D, SWEEP_FAILED, LOFT_FAILED, DRAFT_FAILED, ...) to suggestion strings that ride along automatically.

Manual construction: pick the kind-matching constructor

BrepError is a plain object: { kind, code, message, suggestion?, cause?, metadata? } (src/core/errors.ts). There are 9 kinds, each with a constructor sharing the signature (code, message, cause?, metadata?, suggestion?):

KindConstructorUse for
VALIDATIONvalidationErrorBad input parameters (check these first, before touching the kernel)
KERNEL_OPERATIONkernelErrorKernel op failed (prefer kernelCall unless building the error by hand)
TYPE_CASTtypeCastErrorResult was not the expected shape type (e.g. boolean returned non-3D)
COMPUTATIONcomputationErrorGeometric computation failed (intersection, skeleton, center of mass)
IOioErrorImport/export failure
QUERYqueryErrorShape query failure (e.g. finder not unique)
MODULE_INITmoduleInitErrorInitialisation failure
UNSUPPORTEDunsupportedErrorCapability not supported by the current kernel (ADR-0006) — see the kernel-abstraction skill
SKETCHER_STATEsketcherStateErrorCurrently unused in src; exists for sketcher state transitions

Always thread context through:

  • cause: the original exception. Dropping it destroys kernel diagnostics.
  • metadata: structured context. Real example from src/topology/modifierFns.ts:
return err(
  kernelError('FILLET_FAILED', `Fillet operation failed: ${raw}`, e, {
    operation: 'fillet',
    edgeCount: selectedCount,
    radius,
  })
);
  • suggestion: a recovery hint. The shape() wrapper folds it into the thrown message ("...\nSuggestion: ..."), so it reaches users.

Error codes

BrepErrorCode (src/core/errors.ts) is an as const catalog of ~124 codes grouped by category, with a matching literal-union type. Use BrepErrorCode.X instead of a raw string whenever the code exists — but know two caveats:

  1. BrepError.code is typed string, not the union — a raw-string typo compiles fine. The catalog is advisory; checking it is on the author.
  2. The catalog is incomplete: dozens of codes exist in src only as raw string literals (FILLET_FAILED, WIRE_NOT_CLOSED, THREAD_INVALID_PITCH, and whole families). Grep before assuming a code is new.

To add a new code:

  1. Add the constant to BrepErrorCode in src/core/errors.ts under its category group (kernel-op, validation, IO, ...).
  2. Use it via the kind-matching constructor, or pass it to kernelCall.
  3. Optionally add an entry to ERROR_CODE_SUGGESTIONS in src/core/kernelErrorTranslation.ts so kernelCall auto-attaches a recovery hint.
  4. Optionally add a row to the tables in docs/errors.md (hand-maintained, no CI check — see the staleness warning below).

Consuming Results

NeedUseNotes
Branch on outcomeisOk(r) / isErr(r)Type guards; narrow to Ok<T> / Err<E>
Handle both arms as an expressionmatch(r, { ok: v => ..., err: e => ... })
Extract in a test or scriptunwrap(r)Throws with [kind] CODE: message formatting on Err
Extract with fallbackunwrapOr(r, default) / unwrapOrElse(r, fn)Never use to paper over failures the caller should see
Chain fallible stepsandThen (alias flatMap), or pipeline(input).then(fn).then(fn).resultBoth short-circuit on first Err
Transform value / errormap / mapErr / mapBoth
Combine manycollect(results) (alias all), zip(a, b)collect short-circuits on first Err; zip is re-exported from src/index.ts as zipResults
Side-effect without consumingtap / tapErrtapErr is the idiomatic "log and pass through"

Content truncated.

When not to use it

  • When an operation fails silently without an error channel.
  • When bad geometry is produced with an `Ok` result.
  • When a plain `Error` is thrown from a `*Fns.ts` function.

Limitations

  • The rule to never throw for expected failures is enforced by discipline, not mechanically.
  • The `docs/errors.md` resource is partially stale and may not align with `src/core/errors.ts`.
  • The `withKernel(id, fn)` helper is sync-only and can lead to confusing errors in async code after an `await`.

How it compares

This workflow provides structured error handling with specific error types and translation, unlike a generic approach that might rely on untyped exceptions or silent failures.

Compared to similar skills

result-error-handling side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
result-error-handling (this skill)025dReviewIntermediate
javascript-mastery76moNo flagsBeginner
tech-debt-analyzer58moReviewIntermediate
error-handling22moNo flagsIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

javascript-mastery

davila7

Comprehensive JavaScript reference covering 33+ essential concepts every developer should know. From fundamentals like primitives and closures to advanced patterns like async/await and functional programming. Use when explaining JS concepts, debugging JavaScript issues, or teaching JavaScript fundamentals.

731

tech-debt-analyzer

ailabs-393

This skill should be used when analyzing technical debt in a codebase, documenting code quality issues, creating technical debt registers, or assessing code maintainability. Use this for identifying code smells, architectural issues, dependency problems, missing documentation, security vulnerabilities, and creating comprehensive technical debt documentation.

522

error-handling

EpicenterHQ

Error handling patterns using wellcrafted trySync and tryAsync. Use when writing error handling code, using try-catch blocks, or working with Result types and graceful error recovery.

27

codex-code-review

tyrchen

Perform comprehensive code reviews using OpenAI Codex CLI. This skill should be used when users request code reviews, want to analyze diffs/PRs, need security audits, performance analysis, or want automated code quality feedback. Supports reviewing staged changes, specific files, entire directories, or git diffs.

16

dead-code

parcadei

Find unused functions and dead code in the codebase

16

devtu-fix-tool

mims-harvard

Fix failing ToolUniverse tools by diagnosing test failures, identifying root causes, implementing fixes, and validating solutions. Use when ToolUniverse tools fail tests, return errors, have schema validation issues, or when asked to debug or fix tools in the ToolUniverse framework.

16

Search skills

Search the agent skills registry