{"record":{"id":"433f081eb4803e7a","repo":"FlowiseAI/Flowise","slug":"no-datasource-options-provided-433f08","errorCode":null,"errorMessage":"No datasource options provided","messagePattern":"No datasource options provided","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/components/nodes/recordmanager/MySQLRecordManager/MySQLrecordManager.ts","lineNumber":199,"sourceCode":"        this.config = config\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 { mysqlOptions } = this.config\n        if (!mysqlOptions) {\n            throw new Error('No datasource options provided')\n        }\n        // Prevent using default Postgres port, otherwise will throw uncaught error and crashing the app\n        if (mysqlOptions.port === 5432) {\n            throw new Error('Invalid port number')\n        }\n        const dataSource = new DataSource(mysqlOptions)\n        await dataSource.initialize()\n        return dataSource\n    }\n\n    async createSchema(): Promise<void> {\n        const dataSource = await this.getDataSource()\n        try {\n            const queryRunner = dataSource.createQueryRunner()\n            const tableName = this.sanitizeTableName(this.tableName)\n\n            await queryRunner.manager.query(`create table if not exists \\`${this.sanitizeTableName(tableName)}\\` (\n                \\`uuid\\` varchar(36) primary key default (UUID()),","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/components/nodes/recordmanager/MySQLRecordManager/MySQLrecordManager.ts#L181-L217","documentation":"Thrown by MySQLRecordManager.getDataSource when config.mysqlOptions is falsy. The manager cannot construct a TypeORM DataSource without connection options, so it aborts before attempting new DataSource(undefined). It is a precondition check, not a connection failure.","triggerScenarios":"Instantiating MySQLRecordManager with a config object that omits mysqlOptions, or whose additionalConfig JSON did not parse into a mysqlOptions key. Also when the node's 'Additional Configuration' field is empty and no credential-derived options are merged in.","commonSituations":"Record Manager node wired without a MySQL credential; credential selected but the additionalConfig JSON missing the 'mysqlOptions' wrapper; partial refactor that renamed the key;DATABASE_URL parsing not producing a mysqlOptions object.","solutions":["Supply mysqlOptions in the Record Manager's Additional Configuration JSON, e.g. {\"mysqlOptions\":{\"host\":\"...\",\"port\":3306,\"username\":\"...\",\"password\":\"...\",\"database\":\"...\"}}.","Confirm the selected credential actually populates mysqlOptions; check the node's credential binding.","Validate the JSON parses (a parse failure throws a different 'Invalid JSON' error first) before troubleshooting this one.","If building the manager programmatically, pass { mysqlOptions: {...} } as the config argument."],"exampleFix":"// before\nconst mgr = new MySQLRecordManager({ tableName: 'records' }, {})\n// after\nconst mgr = new MySQLRecordManager(\n  { tableName: 'records' },\n  { mysqlOptions: { host, port: 3306, username, password, database } }\n)","handlingStrategy":"validation","validationCode":"function hasMysqlOptions(cfg: unknown): cfg is { mysqlOptions: Record<string, unknown> } {\n  return !!cfg && typeof cfg === 'object' && !!((cfg as any).mysqlOptions)\n}\nif (!hasMysqlOptions(config)) {\n  throw new Error('Provide mysqlOptions with host/port/username/password/database.')\n}","typeGuard":"function isMysqlConfig(cfg: unknown): cfg is { mysqlOptions: { host: string; port: number; username: string; password: string; database: string } } {\n  const o = (cfg as any)?.mysqlOptions\n  return !!o && typeof o.host === 'string' && typeof o.port === 'number'\n}","tryCatchPattern":"try {\n  await manager.createSchema()\n} catch (e) {\n  if (e instanceof Error && e.message === 'No datasource options provided') {\n    // prompt user to supply a MySQL credential / additionalConfig\n  }\n  throw e\n}","preventionTips":["Always bind a MySQL credential on the Record Manager node.","In CI, smoke-test config with a minimal createSchema() call before running ingestion.","Validate the additionalConfig JSON contains a mysqlOptions key after parse."],"tags":["mysql","record-manager","config","datasource","missing-credentials"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}