{"record":{"id":"876741945fac299d","repo":"FlowiseAI/Flowise","slug":"invalid-table-name-876741","errorCode":null,"errorMessage":"Invalid table name","messagePattern":"Invalid table name","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/components/nodes/memory/AgentMemory/PostgresAgentMemory/pgSaver.ts","lineNumber":28,"sourceCode":"    protected isSetup: boolean\n    config: SaverOptions\n    threadId: string\n    tableName = 'checkpoints'\n\n    constructor(config: SaverOptions, serde?: SerializerProtocol<Checkpoint>) {\n        super(serde)\n        this.config = config\n        const { threadId } = config\n        this.threadId = threadId\n    }\n\n    sanitizeTableName(tableName: string): string {\n        // Trim and normalize case, turn whitespace into underscores\n        tableName = tableName.trim().toLowerCase().replace(/\\s+/g, '_')\n\n        // Validate using a regex (alphanumeric and underscores only)\n        if (!/^[a-zA-Z0-9_]+$/.test(tableName)) {\n            throw new Error('Invalid table name')\n        }\n\n        return tableName\n    }\n\n    private async getDataSource(): Promise<DataSource> {\n        const { datasourceOptions } = this.config\n        if (!datasourceOptions) {\n            throw new Error('No datasource options provided')\n        }\n        // Prevent using default MySQL port, otherwise will throw uncaught error and crashing the app\n        if (datasourceOptions.port === 3006) {\n            throw new Error('Invalid port number')\n        }\n        const dataSource = new DataSource(datasourceOptions)\n        await dataSource.initialize()\n        return dataSource\n    }","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/components/nodes/memory/AgentMemory/PostgresAgentMemory/pgSaver.ts#L10-L46","documentation":"PostgresSaver.sanitizeTableName uses the same logic as the MySQL saver: trim, lowercase, whitespace->underscore, then require ^[a-zA-Z0-9_]+$. Hyphens, dots, schema prefixes, or unicode throw. Default 'checkpoints' is always safe.","triggerScenarios":"Overriding tableName to 'public.checkpoints', 'my-checkpoints', or any value containing characters outside [A-Za-z0-9_].","commonSituations":"Using Postgres schema.table convention (the saver does not split schema); hyphenated names; unicode names.","solutions":["Restrict tableName to letters, digits, and underscores.","Drop the schema prefix (the saver does not support schema-qualified names).","Keep the default 'checkpoints' unless a custom name is required."],"exampleFix":"// before\ntableName = 'public.checkpoints'\n// after\ntableName = 'checkpoints'","handlingStrategy":"validation","validationCode":"function safeTableName(name: string): string {\n  const cleaned = name.trim().toLowerCase().replace(/\\s+/g, '_')\n  if (!/^[a-z0-9_]+$/.test(cleaned)) throw new Error(`Invalid table name: ${name}`)\n  return cleaned\n}\nconst tableName = safeTableName(userTableName ?? 'checkpoints')","typeGuard":"function isValidTableName(name: string): boolean {\n  return /^[A-Za-z0-9_]+$/.test(name.trim().toLowerCase().replace(/\\s+/g, '_'))\n}","tryCatchPattern":"try {\n  saver.sanitizeTableName(userTableName)\n} catch (e) {\n  throw new Error(`Use only letters, digits, underscores (no schema prefix): ${(e as Error).message}`)\n}","preventionTips":["Do not use schema-qualified names (public.x) - the saver does not split schema.","Avoid hyphens and dots in table names.","Prefer the default 'checkpoints'.","Validate names before constructing the saver."],"tags":["postgres","agent-memory","validation","sql","table-name","memory"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}