FlowiseAI/Flowise · error · Error

Error creating ${this.tableName} table

Error message

Error creating ${this.tableName} table

What it means

Thrown by PostgresSaver.setup() when the CREATE TABLE IF NOT EXISTS DDL for the checkpoints table fails. The original TypeORM/Postgres error is logged via console.error but re-thrown as an opaque generic Error, hiding the underlying cause. This runs once per saver instance (guarded by isSetup) on the first getTuple/list/put call.

Source

Thrown at packages/components/nodes/memory/AgentMemory/PostgresAgentMemory/pgSaver.ts:67

        if (this.isSetup) {
            return
        }

        try {
            const queryRunner = dataSource.createQueryRunner()
            const tableName = this.sanitizeTableName(this.tableName)
            await queryRunner.manager.query(`
CREATE TABLE IF NOT EXISTS ${tableName} (
    thread_id TEXT NOT NULL,
    checkpoint_id TEXT NOT NULL,
    parent_id TEXT,
    checkpoint BYTEA,
    metadata BYTEA,
    PRIMARY KEY (thread_id, checkpoint_id));`)
            await queryRunner.release()
        } catch (error) {
            console.error(`Error creating ${this.tableName} table`, error)
            throw new Error(`Error creating ${this.tableName} table`)
        }

        this.isSetup = true
    }

    async getTuple(config: RunnableConfig): Promise<CheckpointTuple | undefined> {
        const dataSource = await this.getDataSource()
        await this.setup(dataSource)

        const thread_id = config.configurable?.thread_id || this.threadId
        const checkpoint_id = config.configurable?.checkpoint_id
        const tableName = this.sanitizeTableName(this.tableName)

        if (checkpoint_id) {
            try {
                const queryRunner = dataSource.createQueryRunner()
                const keys = [thread_id, checkpoint_id]
                const sql = `SELECT checkpoint, parent_id, metadata FROM ${tableName} WHERE thread_id = $1 AND checkpoint_id = $2`

View on GitHub (pinned to abe4a8601a)

Solutions

  1. Inspect the server/terminal log immediately before this error — console.error prints the real cause; fix that root cause (permissions, missing DB, bad tableName).
  2. Grant CREATE (or make the table owner pre-create it) to the connecting role, or pre-create the checkpoints table so CREATE TABLE IF NOT EXISTS is a no-op.
  3. Confirm datasourceOptions.host/database/username are correct by connecting with psql using the same credentials.
  4. Ensure this.tableName passes sanitizeTableName and is not a Postgres reserved word; if customization is needed, rename it.
  5. If you maintain this code, wrap and rethrow with `cause` so callers see the underlying error instead of the generic message.

Example fix

// before
} catch (error) {
    console.error(`Error creating ${this.tableName} table`, error)
    throw new Error(`Error creating ${this.tableName} table`)
}
// after
} catch (error) {
    throw new Error(`Error creating ${this.tableName} table: ${(error as Error).message}`, { cause: error })
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight: verify role can create the table, or that it already exists.
import { DataSource } from 'typeorm'
async function ensureCheckpointsTable(ds: DataSource, tableName: string): Promise<void> {
  const exists = await ds.query(
    `SELECT to_regclass($1) IS NOT NULL AS exists`,
    [`public.${tableName}`]
  )
  if (!exists[0]?.exists) {
    // attempt create with explicit privileges; throw a typed error if it fails
    await ds.query(`CREATE TABLE IF NOT EXISTS ${tableName} (...)`)
  }
}

Type guard

function isSetupError(e: unknown, tableName: string): boolean {
  return e instanceof Error && e.message === `Error creating ${tableName} table`
}

Try / catch

try {
  await saver.getTuple(config)
} catch (e) {
  if (e instanceof Error && /Error creating .* table/.test(e.message)) {
    // inspect server logs for the real cause; check role grants and pre-create the table
  }
  throw e
}

Prevention

When it happens

Trigger: First checkpoint operation after constructing PostgresSaver when: the Postgres user lacks CREATE permission, the database/connection is wrong, the tableName contains characters rejected by Postgres after sanitizeTableName (sanitize only allows [A-Za-z0-9_]), the schema does not exist, or the connection drops mid-DDL.

Common situations: Restricted DB role provisioned without DDL privileges. Misconfigured host/credentials that still connect but to the wrong database. Reserved Postgres table names that pass the regex but collide with system catalogs. Concurrent savers racing on the same table on a connection that times out.

Related errors


AI-assisted analysis of FlowiseAI/Flowise@abe4a8601a (2026-08-12). Data as JSON: /api/errors/bb0700cc440bbd3b. Report an issue: GitHub.