cube-js/cube · error

CubeServer is already listening

Error message

CubeServer is already listening

What it means

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.

Source

Thrown at packages/cubejs-server/src/server.ts:91

        cors: {
          allowedHeaders: 'authorization,content-type,x-request-id',
          ...config.http?.cors,
        },
      },
    };

    this.core = this.createCoreInstance(this.config, systemOptions);
    this.server = null;
  }

  protected createCoreInstance(config: CreateOptions, systemOptions?: SystemOptions): CubeCore {
    return new CubeCore(config, systemOptions);
  }

  public async listen(options: http.ServerOptions = {}): Promise<{app: Express, port: number, server: GracefulHttpServer, version: any }> {
    try {
      if (this.server) {
        throw new Error('CubeServer is already listening');
      }

      const app = express();
      app.use(cors(this.config.http.cors));
      app.use(bodyParser.json({ limit: getEnv('maxRequestSize') }));

      if (this.config.gracefulShutdown) {
        app.use(gracefulMiddleware(this.status, this.config.gracefulShutdown));
      }

      await this.core.initApp(app);

      const enableTls = getEnv('tls');
      if (enableTls) {
        throw new Error('CUBEJS_ENABLE_TLS has been deprecated and removed.');
      }

      this.server = gracefulHttp(http.createServer(options, app));

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Create a new CubeServer instance before calling listen() again
  2. Guard the call: only listen if this.server is not already set (reuse the existing app/server instead)
  3. In tests/hot-reload, close the previous server before listening again
  4. Memoize the listen call in serverless entrypoints (module-level singleton)

Example fix

// before
async function start() {
  await server.listen();
}
start();
// after
let started = false;
async function start() {
  if (!started) {
    await server.listen();
    started = true;
  }
}
start();
Defensive patterns

Strategy: try-catch

Validate before calling

if (server.server) {
  console.warn('CubeServer already listening, skipping listen()');
} else {
  await server.listen();
}

Type guard

const isListening = (s: any): s is { server: object } => !!s?.server;

Try / catch

try {
  await server.listen();
} catch (e) {
  if (e.message === 'CubeServer is already listening') {
    console.warn('Server already started; reusing it');
  } else { throw e; }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02). Data as JSON: /api/errors/2cbb562187a30bd4. Report an issue: GitHub.