remix-run/remix · error · Error

MySQL database + method + () requires config-based construc

Error message

MySQL database  + method + () requires config-based construction

What it means

The MySQL driver supports two construction modes: config-based (pool-managed) and client-based (external connection). Methods that need to create or manage the pool — signalled by #configOrThrow — throw this error when called on a driver built from an existing client, because there is no config to build a pool from.

Source

Thrown at packages/data-table-mysql/src/lib/driver.ts:477

    // tracked to keep close() idempotent.
    if (isMysqlPool(this.#client) && !this.#poolClosed) {
      this.#poolClosed = true
      await this.#client.end()
    }
  }

  async #replacePool(): Promise<void> {
    await this.#closePool().catch(() => undefined)

    if (this.#config) {
      this.#client = createMysqlPool(this.#config)
      this.#poolClosed = false
    }
  }

  #configOrThrow(method: string): string | MysqlPoolOptions {
    if (!this.#config) {
      throw new Error('MySQL database ' + method + '() requires config-based construction')
    }

    return this.#config
  }

  #assertNoOpenTransactions(method: string): void {
    if (this.#transactions.size > 0) {
      throw new Error('MySQL database cannot ' + method + ' while transactions are open')
    }
  }

  #resolveClient(token: TransactionToken | undefined): MysqlQueryable {
    if (!token) {
      return this.#client
    }

    return this.#transactionConnection(token)
  }

View on GitHub (pinned to 9696913134)

Solutions

  1. Construct the driver from a config object (host/user/password/database or uri) so pool-managing methods work
  2. If you must keep the external client, avoid the pool-requiring method and perform the equivalent operation directly on your client
  3. Check the method name in the error message to identify which call needs config

Example fix

// before
const driver = createMysqlDriver(existingClient)
await driver.wipe()
// after
const driver = createMysqlDriver({ uri: MYSQL_URI })
await driver.wipe()
Defensive patterns

Strategy: validation

Validate before calling

// Decide based on construction mode before calling pool-requiring methods
const driverFromConfig = createMysqlDriver({ uri: process.env.MYSQL_URL! })
// use driverFromConfig for wipe()/pool lifecycle; keep client-based drivers for scoped queries

Try / catch

try { await driver.wipe() } catch (e) { if (e instanceof Error && e.message.includes('requires config-based construction')) { /* rebuild driver from config or clean manually */ } throw e }

Prevention

When it happens

Trigger: Constructing the driver with new MysqlDriver(client) (or an equivalent client-injection factory) and then calling a pool-requiring method such as connect/config-dependent lifecycle operations; typically surfaced via a method named in the message, e.g. 'MySQL database wipe() requires config-based construction'.

Common situations: Using an injected client for tests or a managed connection, then calling wipe/reset/pool operations during teardown; switching from config-based to client-based construction without auditing lifecycle calls.

Related errors


AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27). Data as JSON: /api/errors/fddb2d915b4d096e. Report an issue: GitHub.