tursodatabase/turso · error · DatabaseError

overwriting the 'Host' header is not supported

Error message

overwriting the 'Host' header is not supported

What it means

The Session constructor scans config.requestHeaders and throws when any key equals 'host' case-insensitively. Host is a forbidden fetch header — fetch would silently drop the override — so the library rejects it up front to make the failure loud instead of silent. The same check runs per-request in buildHeaders (protocol.ts:242) for headers that only arrive via QueryOptions.requestHeaders.

Solutions

  1. Remove the Host entry from requestHeaders — route by choosing the correct url instead
  2. If you need host-based routing, put the target host in the URL and let fetch set Host itself
  3. If the header object is dynamic, filter it before constructing the Session

Example fix

// before
const session = new Session({
  url: 'https://db.example.com',
  authToken,
  requestHeaders: { Host: 'db.internal.example.com' }, // throws
});

// after
const session = new Session({
  url: 'https://db.internal.example.com',
  authToken,
  requestHeaders: { 'x-custom-trace-id': traceId },
});
Defensive patterns

Strategy: validation

Validate before calling

// strip forbidden headers before constructing the Session
function sanitizeHeaders(headers: Record<string, string> = {}): Record<string, string> {
  const out: Record<string, string> = {};
  for (const [k, v] of Object.entries(headers)) {
    if (k.toLowerCase() === 'host') continue; // fetch forbids setting Host
    out[k] = v;
  }
  return out;
}

Try / catch

try {
  new Session(config);
} catch (e) {
  if (e instanceof DatabaseError && e.message.includes("'Host' header")) {
    delete config.requestHeaders?.Host;
    // retry construction
  }
}

Prevention

When it happens

Trigger: Constructing a Session (or the client that builds one) with requestHeaders: { Host: '...' } or { host: '...' }; passing per-query requestHeaders containing Host via queryOptions, which skips the constructor check and throws at request time with the same message.

Common situations: Porting code that set Host for virtual-host routing with another HTTP client; copy-pasted header objects from curl -H 'Host: ...' recipes; multi-tenant routing attempts through a shared gateway.

Related errors


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

Appendix: source

Thrown at serverless/javascript/src/session.ts:141

 * A database session that manages the connection state and baton.
 * 
 * Each session maintains its own connection state and can execute SQL statements
 * independently without interfering with other sessions.
 */
export class Session {
  private config: SessionConfig;
  private baton: string | null = null;
  private baseUrl: string;
  // Cached autocommit status from the server's last `get_autocommit` answer.
  // A fresh connection is in autocommit (not in a transaction).
  private autocommit: boolean = true;

  constructor(config: SessionConfig) {
    for (const name of Object.keys(config.requestHeaders ?? {})) {
      // `Host` is a forbidden fetch header and would be silently dropped —
      // reject it up front so the caller learns the override never takes effect.
      if (name.toLowerCase() === 'host') {
        throw new DatabaseError("overwriting the 'Host' header is not supported");
      }
    }
    this.config = config;
    this.baseUrl = normalizeUrl(config.url);
  }

  private httpContext(queryOptions?: QueryOptions): HttpContext {
    // Per-query headers are merged over the session-level ones, so a query
    // can override a header the session sets (and both override the
    // standard headers).
    let requestHeaders = this.config.requestHeaders;
    if (queryOptions?.requestHeaders) {
      requestHeaders = { ...requestHeaders, ...queryOptions.requestHeaders };
    }
    return {
      url: this.baseUrl,
      authToken: this.config.authToken,
      remoteEncryptionKey: this.config.remoteEncryptionKey,

View on GitHub (pinned to c1e5928725)