{"id":"8989a89e81468368","repo":"nestjs/nest","slug":"conn-err","errorCode":"CONN_ERR","errorMessage":"CONN_ERR","messagePattern":"CONN_ERR","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"integration/microservices/src/disconnected.controller.ts","lineNumber":23,"sourceCode":"  Post,\n  RequestTimeoutException,\n} from '@nestjs/common';\nimport { ClientProxyFactory } from '@nestjs/microservices';\nimport { Observable, throwError } from 'rxjs';\nimport { catchError, tap } from 'rxjs/operators';\n\n@Controller()\nexport class DisconnectedClientController {\n  @Post()\n  call(@Body() options): Observable<number> {\n    const client = ClientProxyFactory.create(options);\n    return client.send<number, number[]>({ cmd: 'none' }, [1, 2, 3]).pipe(\n      // tap(\n      //   console.log.bind(console, 'data'),\n      //   console.error.bind(console, 'error'),\n      // ),\n      catchError(error => {\n        const { code } = error?.err ?? error ?? { code: 'CONN_ERR' };\n        return throwError(() =>\n          code === 'ECONNREFUSED' ||\n          code === 'CONN_ERR' ||\n          code === 'ENOTFOUND' ||\n          code === 'CONNECTION_REFUSED' ||\n          error.message.includes('Connection is closed.')\n            ? new RequestTimeoutException('ECONNREFUSED')\n            : new InternalServerErrorException(),\n        );\n      }),\n      tap({\n        error: () => client.close(),\n      }),\n    );\n  }\n}\n","sourceCodeStart":5,"sourceCodeEnd":40,"githubUrl":"https://github.com/nestjs/nest/blob/6ec0e2783d15290732447f304d8549b591b9749e/integration/microservices/src/disconnected.controller.ts#L5-L40","documentation":"NestJS microservices error surfaced by DisconnectedClientController (integration/microservices/src/disconnected.controller.ts). ClientProxyFactory.create(options) builds a transport client (TCP/Redis/RabbitMQ/NATS/MQTT) from request-body options, then client.send({cmd:'none'}, [1,2,3]) emits a message. When the transport cannot reach its broker/service, NestJS's ClientProxy emits an error whose code is CONN_ERR (its own 'connection not available' code) or one of ECONNREFUSED/ENOTFOUND/CONNECTION_REFUSED. The catchError at line 22-33 destructures `error?.err ?? error ?? { code: 'CONN_ERR' }` and normalises connection-class codes into RequestTimeoutException('ECONNREFUSED'); the bare `{ code: 'CONN_ERR' }` fallback covers errors with no structured code. This controller exists specifically to demonstrate that disconnection path.","triggerScenarios":"POST to the controller with transport options pointing at a broker/service that isn't running — e.g., body { transport: 'REDIS', options: { host: 'localhost', port: 6379 } } with no Redis up, or a TCP microservice on a dead port. The first emitted message hits a closed/unreachable socket and the stream errors with code CONN_ERR.","commonSituations":"Broker (Redis/RabbitMQ/NATS/MQTT) never started locally; wrong host/port in options; service registry/DNS resolves but nothing listens on that port; firewall/network policy blocks the port; the receiving microservice crashed between connection setup and the send; accepting arbitrary options from the request body (as this controller does) lets clients target unreachable hosts.","solutions":["Start the transport the options point at (e.g., docker run redis, or the partner microservice) and re-issue the request.","Verify host/port in the request body actually have a listener before sending.","Call client.connect() (or rely on NestJS eager connect) and await it so connection failures surface before the first send rather than as CONN_ERR mid-stream.","Do not accept raw transport options from the request body in production — validate/whitelist them, or build the client from trusted config."],"exampleFix":"// before\nconst client = ClientProxyFactory.create(options);\nreturn client.send<number, number[]>({ cmd: 'none' }, [1, 2, 3]).pipe(...)\n\n// after\nif (!options || !options.transport) {\n  throw new BadRequestException('transport options required');\n}\nconst client = ClientProxyFactory.create(options);\nawait client.connect(); // surface connection failure explicitly\nreturn client.send<number, number[]>({ cmd: 'none' }, [1, 2, 3]).pipe(...)","handlingStrategy":"try-catch","validationCode":"// Validate transport options before creating the client\nconst ALLOWED_TRANSPORTS = new Set(['TCP', 'REDIS', 'RMQ', 'NATS', 'MQTT', 'KAFKA']);\n\nfunction isValidTransportOptions(v: unknown): v is { transport: string; options: Record<string, unknown> } {\n  if (typeof v !== 'object' || v === null) return false;\n  const t = (v as any).transport;\n  return typeof t === 'string' && ALLOWED_TRANSPORTS.has(t)\n    && typeof (v as any).options === 'object';\n}\n\n// Optionally probe reachability before sending\nimport { createConnection } from 'node:net';\nasync function canReach(host: string, port: number, ms = 1000) {\n  return new Promise<boolean>(resolve => {\n    const s = createConnection({ host, port }, () => { s.destroy(); resolve(true); });\n    s.setTimeout(ms, () => { s.destroy(); resolve(false); });\n    s.on('error', () => resolve(false));\n  });\n}","typeGuard":"function isConnectionError(e: unknown): boolean {\n  const code = (e as any)?.err?.code ?? (e as any)?.code ?? (e as NodeJS.ErrnoException)?.code;\n  return ['CONN_ERR', 'ECONNREFUSED', 'ENOTFOUND', 'CONNECTION_REFUSED', 'ECONNRESET'].includes(code);\n}","tryCatchPattern":"client.send<number, number[]>({ cmd: 'none' }, [1, 2, 3]).pipe(\n  catchError(error => {\n    const code = error?.err?.code ?? error?.code ?? 'CONN_ERR';\n    if (['CONN_ERR', 'ECONNREFUSED', 'ENOTFOUND', 'CONNECTION_REFUSED'].includes(code)) {\n      return throwError(() => new RequestTimeoutException('broker unreachable'));\n    }\n    return throwError(() => new InternalServerErrorException(error?.message));\n  }),\n  tap({ error: () => client.close() }),\n)","preventionTips":["Start the broker/service the transport points at before issuing requests.","Await client.connect() so connection failures surface before the first send.","Never accept raw transport options from the request body in production — whitelist them.","Centralise the connection-error normalisation (the codes listed in catchError) into one filter/operator."],"tags":["microservices","nestjs","transport","connection","rxjs"],"analyzedSha":"6ec0e2783d15290732447f304d8549b591b9749e","analyzedAt":"2026-08-03T17:42:23.673Z","schemaVersion":2}