tursodatabase/turso · critical · Error

invalid config: url is required

Error message

invalid config: url is required

What it means

The Connection constructor validates the config synchronously and throws when `config.url` is missing or empty. Every statement this class executes is an HTTP round trip to that URL, so there is no default endpoint and construction cannot proceed without one.

Solutions

  1. Set url to the database endpoint (libsql://... or https://...)
  2. Fail fast at startup if the env var is missing, before constructing the Connection
  3. Double-check the config key is exactly `url`

Example fix

// before
const conn = new Connection({ authToken: process.env.TURSO_AUTH_TOKEN });
// after
const url = process.env.TURSO_DATABASE_URL;
if (!url) throw new Error('TURSO_DATABASE_URL is not set');
const conn = new Connection({ url, authToken: process.env.TURSO_AUTH_TOKEN });
Defensive patterns

Strategy: validation

Validate before calling

if (typeof config?.url !== 'string' || config.url.length === 0) {
  throw new Error('Connection requires config.url (e.g. libsql://db.turso.io)');
}
const conn = new Connection(config);

Type guard

const hasUrl = (c: Config): c is Config & { url: string } =>
  typeof c?.url === 'string' && c.url.length > 0;

Prevention

When it happens

Trigger: `new Connection({ authToken })` with no url; a url read from an unset environment variable (undefined) or an empty string; a typo'd config key such as `uri` or `endpoint`.

Common situations: Deployments missing TURSO_DATABASE_URL / LIBSQL_URL; CI running with a partial .env; config objects assembled conditionally where one branch omits the url key.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


AI-assisted analysis of tursodatabase/turso@c1e5928725 (2026-08-20). Data as JSON: /api/errors/7728cf953e64f1c3. Report an issue: GitHub.

Appendix: source

Thrown at serverless/javascript/src/connection.ts:129

 * ]);
 *
 * // Option 2: reusable pool for repeated parallel work
 * const pool = Array.from({ length: 4 }, () => connect(config));
 * const results = await Promise.all(
 *   queries.map((sql, i) => pool[i % pool.length].all(sql))
 * );
 * ```
 */
export class Connection {
  private config: Config;
  private session: Session;
  private isOpen: boolean = true;
  private defaultSafeIntegerMode: boolean = false;
  private execLock: AsyncLock = new AsyncLock();

  constructor(config: Config) {
    if (!config.url) {
      throw new Error("invalid config: url is required");
    }
    this.config = config;
    this.session = new Session(config);

    // Define inTransaction property
    Object.defineProperty(this, 'inTransaction', {
      get: () => this.session.inTransaction,
      enumerable: true
    });
  }

  /**
   * Whether the database is currently in a transaction.
   *
   * Derived from the server's `get_autocommit` status (refreshed on every
   * request), so it reflects the connection's real transaction state — the
   * same as `sqlite3_get_autocommit()` on the native bindings — including
   * transactions opened with a raw `BEGIN`, not just via `transaction()`.

View on GitHub (pinned to c1e5928725)