{"record":{"id":"2cbb562187a30bd4","repo":"cube-js/cube","slug":"cubeserver-is-already-listening","errorCode":null,"errorMessage":"CubeServer is already listening","messagePattern":"CubeServer is already listening","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cubejs-server/src/server.ts","lineNumber":91,"sourceCode":"        cors: {\n          allowedHeaders: 'authorization,content-type,x-request-id',\n          ...config.http?.cors,\n        },\n      },\n    };\n\n    this.core = this.createCoreInstance(this.config, systemOptions);\n    this.server = null;\n  }\n\n  protected createCoreInstance(config: CreateOptions, systemOptions?: SystemOptions): CubeCore {\n    return new CubeCore(config, systemOptions);\n  }\n\n  public async listen(options: http.ServerOptions = {}): Promise<{app: Express, port: number, server: GracefulHttpServer, version: any }> {\n    try {\n      if (this.server) {\n        throw new Error('CubeServer is already listening');\n      }\n\n      const app = express();\n      app.use(cors(this.config.http.cors));\n      app.use(bodyParser.json({ limit: getEnv('maxRequestSize') }));\n\n      if (this.config.gracefulShutdown) {\n        app.use(gracefulMiddleware(this.status, this.config.gracefulShutdown));\n      }\n\n      await this.core.initApp(app);\n\n      const enableTls = getEnv('tls');\n      if (enableTls) {\n        throw new Error('CUBEJS_ENABLE_TLS has been deprecated and removed.');\n      }\n\n      this.server = gracefulHttp(http.createServer(options, app));","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-server/src/server.ts#L73-L109","documentation":"CubeServer.listen() starts the HTTP server and stores it on this.server. If listen() is called again on the same CubeServer instance while it is already listening, it throws 'CubeServer is already listening' because a single instance can only bind once.","triggerScenarios":"Calling server.listen() twice on the same CubeServer instance — e.g. in dev hot-reload, in tests that reuse the server, or in serverless bootstrap code that re-executes module init.","commonSituations":"HMR / nodemon re-running bootstrap without recreating the server; test suites calling listen in a shared beforeAll for each test file; accidentally calling listen both in an init function and at module top-level.","solutions":["Create a new CubeServer instance before calling listen() again","Guard the call: only listen if this.server is not already set (reuse the existing app/server instead)","In tests/hot-reload, close the previous server before listening again","Memoize the listen call in serverless entrypoints (module-level singleton)"],"exampleFix":"// before\nasync function start() {\n  await server.listen();\n}\nstart();\n// after\nlet started = false;\nasync function start() {\n  if (!started) {\n    await server.listen();\n    started = true;\n  }\n}\nstart();","handlingStrategy":"try-catch","validationCode":"if (server.server) {\n  console.warn('CubeServer already listening, skipping listen()');\n} else {\n  await server.listen();\n}","typeGuard":"const isListening = (s: any): s is { server: object } => !!s?.server;","tryCatchPattern":"try {\n  await server.listen();\n} catch (e) {\n  if (e.message === 'CubeServer is already listening') {\n    console.warn('Server already started; reusing it');\n  } else { throw e; }\n}","preventionTips":["Guard with `if (server.server)` before listen()","Use a module-level singleton for serverless/hot-reload entrypoints","Close the previous server before starting a new one in tests"],"tags":["server","lifecycle","http"],"backgroundTag":"server-already-listening","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}