Skip to main content
@craft-ts
LearnLearn with EffectAI agentsGuideReference
@craft-ts/core@craft-ts/component@craft-ts/dev-tools@craft-ts/effect@craft-ts/style@craft-ts/style-testing@craft-ts/i18n@craft-ts/i18n-effect@craft-ts/mcp
ExamplesMigrationEffect compatibility & maturityAdopting CraftTS progressivelyPress kitRoadmapBacklog
Beta
  • Learn
  • Learn with Effect
  • AI agents
  • Guide
  • Reference
  • Packages
  • Resources
  • Guide overview
  • Create a project
i.Core concepts
  • The mental model
  • Which primitive should I use?
  • Anatomy of a primitive
  • Generators and yield*
  • Insertions
  • Typed insertion pipes
  • Exceptions as values
ii.Managing state
  • Local state
  • State machines
  • query
  • Mutations
  • queryParams
  • asyncProcess
  • Selecting
  • Reacting to mutations
  • Collections
  • Collection utilities
  • Persistence
  • GlobalPersisterHandler
  • Pagination placeholders
  • Schema validation
iii.Recommended approaches
  • Inject at the point of use
iv.Structuring the app
  • craftService
  • Service scopes
  • Shaping the public API
  • Abstract services
  • App start
  • Lazy services
  • Server functions
  • craftRegisterFor
  • Target wrapper
v.Routing & type-safe DI
  • Setup
  • CLI automation
  • ESLint rules
  • Route providers
  • Route guards
  • Route exception handling
  • Non-blocking navigation
  • Global error component
  • Route load errors
  • Scaling routes
vi.Components & templates
  • Components
  • Activating the style system
  • Typed styles
  • Defining a design system
  • Tokens and variables
  • Global foundation and fonts
  • Pseudo-elements and animations
  • Axes and the matrix
  • Context obligations
  • Testing visual states
  • Text contrast
  • Visual attestation
  • Template obligations
  • Typed CSS variables
  • Fine-grained reactivity
  • Progressive rendering
  • Directives and .pipe(...)
  • settledValue & pendingNode
  • Accessibility
  • Customization
  • Content projection
  • Styling a component
  • Template migrator
vii.Forms
  • Overview
  • Validators
  • Submitting
  • Nested forms
  • Exception handling
  • Complete examples
viii.Testing
  • Testing services
  • Testing components
  • Type-level tests
  • Browser boundaries
  • Page stability
  • Architecture rules
    • Overview
    • Declarative baseline
    • Unique identities
    • HTTP endpoint ownership
    • Computed purity
    • Dependency cycles
    • Mutation reactions
    • Route DI proofs
    • Route component files
    • Path boundaries
    • Exclusive links
    • Persisted identities
    • insertSelect keys
    • craftEffect and network
    • craftEffect and imperative sync
    • Interactive element names
    • Metric thresholds
    • Server-state loaders
    • Primitive loader requirements
  • Extensible architecture graph
  • Graph insights
  • Craft graph vs Nx
ix.Reactivity utilities
  • craftComputed
  • craftEffect
  • craftMethod
  • source$
  • on$
  • fromEventToSource$
  • sourceFromEvent
  • afterRecomputation
x.Internationalisation
  • Type-safe i18n
  • The catalogue
  • Tokens
  • The runtime
  • With Effect
xi.Deployment (experimental)
  • Overview
  • Manifest reference
  • Diagnostics
  • Providers
  • Alchemy provider
xii.Going further
  • SSR and hydration
  • Effect integration
  • Program operators
  • Pattern matching
  • Observability
  • AI agents
  • Temporal runtime
  1. Routing & type-safe DI
  2. Global error component

Global error component#

One component, declared once, for every failure a route decided not to handle locally.

Use it when several exception codes deserve the same screen, or as the backstop for unexpected errors. Not when a specific failure needs its own UI — renderComponent(...) in the route's handler is more precise. See Route exception handling.

When a route exception handler delegates to globalError(), the outlet renders one application-wide error component and feeds it the exception. That component can read all of its possible exceptions — typed and exhaustive — because the codes routed to it are mirrored in a global registry maintained automatically by ESLint.

Register the component#

Pass withErrorComponent(...) directly to provideCraftRouter(...) (mixed with your router features):

ts
provideCraftRouter(
  appRoutes.toRoutes(),
  withComponentInputBinding(),
  withErrorComponent({
    component: MyGlobalErrorScreen,
    componentDeps:
      {} as import('./my-global-error-screen').GenDeps_MyGlobalErrorScreen,
  }),
),

It also works standalone via provideCraftLoading(withErrorComponent({ component, componentDeps })).

Consume the exception#

ts
export const MyGlobalErrorScreen = craftComponent(
  'MyGlobalErrorScreen',
  {},
  function* () {
    // Signal<USER_DISABLED | HttpError | …>
    const error = yield* CraftGlobalError();

    const message = computed(() => {
      switch (error()?.code) {
        case 'USER_DISABLED':
          return 'This account is disabled.';
        default:
          return 'Something went wrong.';
      }
    });

    return div(h1(() => message()));
  },
);

CraftGlobalError() is typed as the union of every exception any route delegates to the global component, so switch (error().code) is exhaustively typed. The outlet writes the active exception into CRAFT_GLOBAL_ERROR just before rendering the component.

The registry (auto-maintained)#

The union comes from CraftGlobalExceptionRegistry, keyed by route path and code:

ts
declare module '@craft-ts/core' {
  interface CraftGlobalExceptionRegistry {
    'user/:userId': {
      USER_DISABLED: CraftRouteExceptionType<
        typeof demoRoutes,
        'user/:userId',
        'USER_DISABLED'
      >;
      HttpError: CraftRouteExceptionType<
        typeof demoRoutes,
        'user/:userId',
        'HttpError'
      >;
    };
  }
}

Do not edit this block by hand. The craft-ts/global-exception-registry-match ESLint rule detects every handleExceptions handler that calls globalError() and keeps the registry in sync:

bash
npx nx lint demo --fix

A missing entry is reported as an error; --fix inserts the [path][code] entry. CraftRouteExceptionType resolves the typed exception object for a code on a route from the collection's route definitions (no type checker required — the rule builds the reference from the collection variable and the path/code literals).

The screen itself still needs an armed RouteExceptionComponentCheckedDI in app.config.ts. Architecture tests fail if that proof is missing.

Default behaviour#

If no withErrorComponent is configured, globalError() and unhandled thrown errors leave the outlet in its error state without a component. Provide a global error component to render a fallback UI.

See Also#

  • Route exception handling — where globalError() is returned

  • Route load errors

  • Non-blocking navigation

  • Architecture rules — assertRouteDiProofs keeps the error-screen proof armed

←Non-blocking navigationRoute load errors→

On this page

  • Register the component
  • Consume the exception
  • The registry (auto-maintained)
  • Default behaviour
  • See Also

@craft-ts · MIT licensed

GitHubnpm

Search