Profiles·Public

@planetscale/database

semver>=1.0.0postconditions6functions3last verified2026-06-24coverage score100%

Postconditions: what we check

  • execute · database-error
    error
    WhenAny failure during query execution: network/DNS failure (TypeError: fetch failed), authentication failure (401/403), invalid query (400), PlanetScale server error (500), or database unavailable. PlanetScale uses HTTP transport — all the failure modes of network calls apply.
    ThrowsDatabaseError (extends Error) — thrown on all non-ok HTTP responses. Properties: message (string), status (HTTP status code), body (VitessError with code and message). TypeError — thrown on network/fetch failures ("TypeError: fetch failed" on connection issues).
    Required handlingCaller MUST wrap execute() in try/catch. Database failures in production cause silent data loss or unhandled exceptions that crash the request handler. Minimum handling: try { const { rows } = await conn.execute( 'SELECT * FROM users WHERE id = ?', [userId] ); return rows; } catch (error) { if (error instanceof DatabaseError) { console.error('Query failed:', error.message, 'status:', error.status); } throw error; }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1][2]
  • execute · unknown-error
    warning
    Whenexecute() is called and PlanetScale's API returns a non-JSON HTTP response — most commonly Cloudflare infrastructure errors (HTTP 520–530) that return HTML error pages instead of JSON. Also triggered when running inside Cloudflare Workers where the Cloudflare error detection is always active. The UnknownError contains a ResponseContext (status, statusText, truncated body, headers) for debugging. This is distinct from DatabaseError: UnknownError means the PlanetScale API itself was not reached — a Cloudflare proxy or network infrastructure layer returned an error.
    ThrowsUnknownError (extends DatabaseError) with: .name === 'UnknownError' .status = HTTP status code (520–530 for Cloudflare, or other non-2xx) .body.code === 'UNKNOWN' .context = { status, statusText, body (first 4096 chars), headers } Message: "Cloudflare error: HTTP <status>" for Cloudflare-range codes, "Expected JSON response from database API, got HTTP <status>" otherwise. NOTE: UnknownError IS-A DatabaseError — instanceof DatabaseError catches it. But if you need the .context property for logging, check error.name === 'UnknownError' or error instanceof UnknownError.
    Required handlingFor apps deployed on Cloudflare Workers or behind Cloudflare proxies, add specific handling for UnknownError to distinguish infrastructure failures from database errors: import { DatabaseError } from '@planetscale/database'; try { const result = await conn.execute('SELECT 1'); } catch (error) { if (error instanceof DatabaseError) { if (error.name === 'UnknownError') { // Cloudflare or infrastructure error — log context for debugging console.error('Infrastructure error:', error.context); throw new Error('Database infrastructure unavailable'); } // Standard database error (auth, constraint, syntax) console.error('DB error:', error.status, error.body.code); } throw error; }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[3]
  • transaction · database-error
    error
    WhenAny failure during the transaction: network failure at any step, authentication failure, constraint violation, PlanetScale server error, or unhandled error thrown inside the transaction callback. The transaction is rolled back automatically, but the error still propagates.
    ThrowsDatabaseError — on network or API failures at any point in the transaction. TypeError — on network/fetch failures. Any error thrown inside the transaction callback propagates to the caller.
    Required handlingCaller MUST wrap transaction() in try/catch. Transaction failures leave the database in a rolled-back state — callers need to handle the error to retry or inform the user. try { await conn.transaction(async (tx) => { await tx.execute('INSERT INTO orders (id, user_id) VALUES (?, ?)', [orderId, userId]); await tx.execute('UPDATE inventory SET count = count - 1 WHERE id = ?', [itemId]); }); } catch (error) { console.error('Transaction failed, rolled back:', error); throw error; }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1][2]
  • transaction · unknown-error
    warning
    Whentransaction() is called and any of the underlying HTTPS requests (BEGIN, statement execution, COMMIT, or ROLLBACK) receives a non-JSON response from a Cloudflare proxy or infrastructure layer. Because transaction() executes multiple requests, UnknownError can occur at any phase — including during ROLLBACK, which means the rollback itself may not complete cleanly.
    ThrowsUnknownError (extends DatabaseError) — same type as execute()'s unknown-error. If UnknownError occurs during ROLLBACK (in the catch block), the original error is re-thrown by the outer catch, meaning the transaction rollback may have been incomplete. Callers cannot distinguish "rolled back cleanly" from "rollback also failed" unless they check for UnknownError specifically.
    Required handlingFor Cloudflare-deployed apps, wrap transaction() and check for UnknownError: try { await conn.transaction(async (tx) => { await tx.execute('INSERT INTO orders ...', [orderId]); await tx.execute('UPDATE inventory ...', [itemId]); }); } catch (error) { if (error instanceof DatabaseError) { if (error.name === 'UnknownError') { // Infrastructure failure — rollback may not have completed // Consider manual cleanup or idempotent retry console.error('Infrastructure error during transaction:', error.context); } } throw error; }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[3]
  • refresh · refresh-authentication-error
    error
    Whenrefresh() is called with invalid or expired credentials (wrong username/password in config, or token revoked). PlanetScale returns HTTP 401 Unauthorized or 403 Forbidden with a VitessError JSON body. This is the most common failure path for refresh() — callers using refresh() in connection pools or scheduled jobs may not notice when credentials rotate.
    ThrowsDatabaseError with status 401 or 403. error.body.code will be a Vitess error code (typically 'UNAUTHENTICATED' or 'PERMISSION_DENIED'). error.message describes the authentication failure.
    Required handlingWrap refresh() in try/catch. Authentication failures on refresh() indicate a credentials problem that will affect all subsequent execute() calls too — fail fast and alert: try { await conn.refresh(); } catch (error) { if (error instanceof DatabaseError && (error.status === 401 || error.status === 403)) { console.error('PlanetScale auth failed — check credentials:', error.message); // Do not proceed with queries — all will fail with the same error throw new Error('Database authentication failed'); } throw error; }
    costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[3]
  • refresh · refresh-network-error
    error
    Whenrefresh() is called but the PlanetScale host is unreachable (DNS failure, TCP connection refused, timeout, or the host is down). The underlying fetch() call throws a TypeError. This is distinct from DatabaseError — it means the HTTP request never completed. Common in: cold-start pre-warming scripts, connection pool initialization, health checks.
    ThrowsTypeError with message like "fetch failed" or "ECONNREFUSED" or "ETIMEDOUT". The error is NOT a DatabaseError — it does not have .status or .body properties. Check: !(error instanceof DatabaseError) to distinguish network failures.
    Required handlingHandle both DatabaseError and TypeError from refresh(): try { await conn.refresh(); } catch (error) { if (error instanceof DatabaseError) { // API-level failure (auth, server error) console.error('Session creation failed:', error.status, error.message); } else if (error instanceof TypeError) { // Network-level failure (DNS, connectivity) console.error('Cannot reach PlanetScale:', error.message); } throw error; }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[3][4]

Sources

Every postcondition cites at least one of these. Grouped by source type; numbered to match the footnotes above.

Official documentation
Source code

Research notes

Curator notes from SOURCES.md captured when the profile was written so you can verify the reasoning, not just the rules.

Sources — @planetscale/database

Claim: execute() throws DatabaseError on HTTP failures

Source: GitHub source code — src/index.ts https://github.com/planetscale/database-js/blob/main/src/index.ts

DatabaseError is defined with status (HTTP code) and body (VitessError) properties. The execute() method throws DatabaseError on non-ok HTTP responses.

Source: PlanetScale documentation https://planetscale.com/docs/vitess/tutorials/planetscale-serverless-driver

Official documentation for the serverless driver.

Claim: DatabaseError class hierarchy

class DatabaseError extends Error {
  body: VitessError;   // { code: string, message: string }
  status: number;      // HTTP status code
}

Source: GitHub source code — exported from src/index.ts

Claim: transaction() rolls back on unhandled errors

Source: PlanetScale documentation and SDK README https://github.com/planetscale/database-js#transactions

"If any unhandled errors are thrown during execution of the transaction, it will be rolled back."

Claim: Network errors throw TypeError

Source: GitHub issue #142 https://github.com/planetscale/database-js/issues/142

"TypeError: fetch failed" is thrown when the network connection fails.

Package Metadata

Need a different package?
Request a profile