Skip to content

ExternalExceptionFilterContext

reference
3 min readUpdated

Kind: Class

Source: packages/core/exceptions/external-exception-filter-context.ts

Part of: Core

ExternalExceptionFilterContext builds exception handling contexts for externally invoked handlers, such as controllers or gateway endpoints. It resolves local and global exception filters, then creates an ExternalExceptionsHandler configured to apply them in the correct order.

Extends: BaseExceptionFilterContext

Methods

MethodSignatureReturns
createcreate(instance: Controller, callback: RouterProxyCallback, module: string, contextId: undefined, inquirerId: string)ExternalExceptionsHandler
getGlobalMetadatagetGlobalMetadata(contextId: undefined, inquirerId: string)T

Where it refuses work

  • ExternalExceptionFilterContext stops the work with an early return when isEmpty(filters).
  • ExternalExceptionFilterContext stops the work with an early return when !this.config.
  • ExternalExceptionFilterContext stops the work with an early return when contextId === STATIC_CONTEXT && !inquirerId.

Diagram

mermaid
graph LR
  A[External Handler Callback] --> B[ExternalExceptionFilterContext]
  B --> C[Resolve Method and Class Filters]
  B --> D[Read Global Filter Metadata]
  C --> E[ExternalExceptionsHandler]
  D --> E
  E --> F[Handle Thrown Exceptions]

Usage

ts
import { ExternalExceptionFilterContext } from '@nestjs/core/exceptions/external-exception-filter-context';

// Typically created and used internally by the Nest runtime.
const exceptionFilterContext = new ExternalExceptionFilterContext(
  container,
  applicationConfig,
);

// Create an exception handler for a controller method.
const exceptionHandler = exceptionFilterContext.create(
  usersController,
  usersController.findOne,
  moduleRef,
);

// Inspect globally configured exception filters when needed.
const globalFilters = exceptionFilterContext.getGlobalMetadata();

// Use the generated handler when invoking the external callback.
try {
  await usersController.findOne('123');
} catch (error) {
  await exceptionHandler.next(error, host);
}

AI Coding Instructions

  • Use create() to generate a dedicated ExternalExceptionsHandler for each external callback context rather than reusing handlers across unrelated routes or handlers.
  • Preserve filter ordering: the context resolves and reverses applicable filters so method-, class-, and global-level filters execute as expected.
  • Use getGlobalMetadata() when extending filter resolution behavior; account for both static global filters and request-scoped global filters.
  • Treat this class as framework infrastructure: application code should generally configure filters through Nest APIs such as useGlobalFilters() or @UseFilters().

How it works

ExternalExceptionFilterContext is an exception-filter context builder for externally created handlers. It extends BaseExceptionFilterContext, accepts a NestContainer and optional ApplicationConfig, and passes the container to its base class. packages/core/exceptions/external-exception-filter-context.ts:14-20

create()

create(instance, callback, module, contextId?, inquirerId?) stores module as the inherited moduleContext, creates an ExternalExceptionsHandler, resolves exception-filter metadata for the supplied controller instance and callback, and returns that handler. packages/core/exceptions/external-exception-filter-context.ts:22-43

The resolved metadata combines global filters, controller-class filters, and callback-method filters in that order through ContextCreator.createContext(). packages/core/helpers/context-creator.ts:16-40 It reads class metadata from the instance prototype’s constructor and method metadata from the callback, using the EXCEPTION_FILTERS_METADATA key passed by create(). packages/core/exceptions/external-exception-filter-context.ts:32-38 packages/core/helpers/context-creator.ts:43-52

Before assigning resolved filters to the handler, create() reverses their array. If the resolved array is empty, it returns the new handler without assigning custom filters. packages/core/exceptions/external-exception-filter-context.ts:31-43

Inherited filter resolution accepts an object with a catch function or a class/function with a name; it discards other entries. For objects, it uses the object directly. For classes, it looks up an injectable in the stored module and gets its instance for the supplied context and inquirer IDs; missing module context, module, injectable, or instance causes that filter to be omitted. packages/core/exceptions/base-exception-filter-context.ts:18-36 packages/core/exceptions/base-exception-filter-context.ts:39-71

Each retained filter becomes metadata containing its catch method bound to the filter instance and exception metatypes read from FILTER_CATCH_EXCEPTIONS metadata on its constructor; absent catch metadata becomes an empty metatype array. packages/core/exceptions/base-exception-filter-context.ts:32-36 packages/core/exceptions/base-exception-filter-context.ts:73-77

Global-filter lookup

getGlobalMetadata(contextId?, inquirerId?) returns an empty array when the context was constructed without an ApplicationConfig. packages/core/exceptions/external-exception-filter-context.ts:46-52

With configuration, a static context with no inquirer ID returns ApplicationConfig.getGlobalFilters() directly. packages/core/exceptions/external-exception-filter-context.ts:53-56 For another context or any inquirer ID, it gets global request-filter wrappers, resolves each wrapper for that context and inquirer, drops falsy instance hosts, extracts their instances, and concatenates them after the static global filters. packages/core/exceptions/external-exception-filter-context.ts:57-65

ApplicationConfig stores static global filters separately from global request-filter wrappers; its related add methods append entries to those arrays. packages/core/application-config.ts:17-23 packages/core/application-config.ts:64-74 packages/core/application-config.ts:122-128

Resulting handler and externally created callbacks

The returned ExternalExceptionsHandler selects the first assigned filter whose metatype list is empty or contains a constructor matched by exception instanceof; it invokes that filter’s bound catch function. If no custom filter matches, it calls its inherited catch, which logs non-intrinsic Error instances and rethrows the exception. packages/core/exceptions/external-exceptions-handler.ts:11-17 packages/core/exceptions/external-exceptions-handler.ts:26-36 packages/common/utils/select-exception-filter-metadata.util.ts:3-13 packages/core/exceptions/external-exception-filter.ts:6-15

ExternalContextCreator constructs this context from a container and its application configuration, calls create() while building an external callback, and—when filters are enabled—wraps the callback in ExternalErrorProxy. packages/core/helpers/external-context-creator.ts:56-88 packages/core/helpers/external-context-creator.ts:128-134 packages/core/helpers/external-context-creator.ts:178-184 That proxy catches errors from the target callback, creates an ExecutionContextHost from callback arguments, sets its context type, and passes the error and host to the handler’s next() method. packages/core/helpers/external-proxy.ts:6-18

Validation, errors, and side effects

This class has no explicit argument validation and no explicit throw statement. Its visible state mutation is assigning this.moduleContext during create(). packages/core/exceptions/external-exception-filter-context.ts:22-31 It also allocates a new ExternalExceptionsHandler per create() call. packages/core/exceptions/external-exception-filter-context.ts:29-32

The handler’s setCustomFilters() throws InvalidExceptionFilterException if called with a non-array value, although this context passes the array returned by createContext(). packages/core/exceptions/external-exceptions-handler.ts:19-24 packages/core/helpers/context-creator.ts:28-40

Relationships

  • IMPORTS → EXCEPTION_FILTERS_METADATA
  • IMPORTS → Controller
  • IMPORTS → ExceptionFilterMetadata
  • IMPORTS → isEmpty

Was this page helpful?

Download as PDF
ExternalExceptionFilterContext — NestJS head-to-head