nestjs/nest · error · InternalServerErrorException

HTTP adapter does not support filtering on host: "${host}"

Error message

HTTP adapter does not support filtering on host: "${host}"

What it means

Host-restricted routes (`@Controller({ path: 'x', host: 'api.example.com' })`) are implemented as a wrapper that matches `req.hostname` against the configured host patterns and falls through to `next()` when nothing matches. When the underlying HTTP adapter registers the handler directly (not as middleware with a next function — the Fastify case) there is no fallback, so a request whose hostname matches none of the patterns ends in InternalServerErrorException 'HTTP adapter does not support filtering on host'.

Source

Thrown at packages/core/router/router-explorer.ts:388

    ) => {
      (req as Record<string, any>).hosts = {};
      const hostname = httpAdapterRef.getRequestHostname(req) || '';

      for (const exp of hostRegExps) {
        const match = hostname.match(exp.regexp);
        if (match) {
          if (exp.keys.length > 0) {
            exp.keys.forEach((key, i) => (req.hosts[key.name] = match[i + 1]));
          } else if (exp.regexp && match.groups) {
            for (const groupName in match.groups) {
              req.hosts[groupName] = match.groups[groupName];
            }
          }
          return handler(req, res, next);
        }
      }
      if (!next) {
        throw new InternalServerErrorException(
          unsupportedFilteringErrorMessage,
        );
      }
      return next();
    };
  }

  private applyVersionFilter<T extends HttpServer>(
    router: T,
    routePathMetadata: RoutePathMetadata,
    handler: Function,
  ) {
    const version = this.routePathFactory.getVersion(routePathMetadata)!;
    return router.applyVersionFilter(
      handler,
      version,
      routePathMetadata.versioningOptions!,
    );

View on GitHub (pinned to dd75d7bd8c)

Solutions

  1. Add the hostnames you actually serve to the filter: `@Controller({ host: ['api.example.com', 'localhost'] })` or a parametrized pattern like `:subdomain.example.com`.
  2. Switch to the Express adapter if full host-based (virtual host) routing is a hard requirement — it supports the middleware fallback.
  3. Fix the Host header at the proxy/ingress level (preserve upstream Host) so the app sees the expected hostname.
  4. As a safety net, map the resulting InternalServerError to a 404 with an exception filter for unmatched host traffic.

Example fix

// before (Fastify + only prod host in filter -> curl http://localhost:3000/x => 500)
@Controller({ path: 'reports', host: 'api.example.com' })
export class ReportsController {}

// after
@Controller({ path: 'reports', host: ['api.example.com', 'localhost'] })
export class ReportsController {}
Defensive patterns

Strategy: validation

Validate before calling

// Validate Host before host-filtered routes run; respond 404 instead of a 500
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

const ALLOWED_HOSTS = ['api.example.com', 'localhost'];

@Injectable()
export class HostAllowlistMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    const hostname = (req.hostname || '').toLowerCase();
    if (!ALLOWED_HOSTS.includes(hostname)) {
      return res.status(404).json({ statusCode: 404, message: 'Unknown host' });
    }
    next();
  }
}
// register with consumer.apply(HostAllowlistMiddleware).forRoutes('*') BEFORE host-filtered controllers

Prevention

When it happens

Trigger: Using Fastify with host-based controllers and accessing the app through a hostname/IP not covered by any pattern (localhost, 127.0.0.1, container IP, another domain); a host regex that does not account for the port-bearing Host header value; moving an Express app with virtual hosts to Fastify where the middleware-style registration is unavailable; API gateways rewriting Host before the request reaches the service.

Common situations: Local development against localhost for a controller restricted to 'api.example.com'; Kubernetes ingress sending internal hostnames; multi-tenant SaaS routing by subdomain behind proxies; smoke tests hitting the pod IP directly.

Related errors


AI-assisted analysis of nestjs/nest@dd75d7bd8c (2026-08-21). Data as JSON: /api/errors/ad31b34b6ec38414. Report an issue: GitHub.