Sequelizeでテーブル作成時のエラー
前提
docker-composeで立てたMySQLのコンテナとNode.jsによるAPIコンテナがある。
接続の確認自体は済んでいるものとする。
https://sequelize.org/docs/v6/getting-started/#testing-the-connection
APIコンテナからSequelizeを用いて
Model.sync({force: true});
でテーブルを作成しようとした際にエラーが発生。
todo-api  | Executing (default): CREATE TABLE IF NOT EXISTS `Tasks` (`id` INTEGER NOT NULL auto_increment , `name` VARCHAR(255) NOT NULL, `completed` TINYINT(1) NOT NULL, `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB;
todo-api  | node:internal/process/promises:288
todo-api  |             triggerUncaughtException(err, true /* fromPromise */);
todo-api  |             ^
todo-api  | 
todo-api  | Error
todo-api  |     at Query.run (/home/node/node_modules/sequelize/lib/dialects/mysql/query.js:52:25)
todo-api  |     at /home/node/node_modules/sequelize/lib/sequelize.js:314:28
todo-api  |     at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
todo-api  |     at async MySQLQueryInterface.createTable (/home/node/node_modules/sequelize/lib/dialects/abstract/query-interface.js:98:12)
todo-api  |     at async Task.sync (/home/node/node_modules/sequelize/lib/model.js:942:7)
todo-api  |     at async /home/node/models/tasks.js:20:5 {
todo-api  |   name: 'SequelizeDatabaseError',
todo-api  |   parent: Error: Table 'todo.tasks' doesn't exist
todo-api  |       at Packet.asError (/home/node/node_modules/mysql2/lib/packets/packet.js:728:17)
todo-api  |       at Query.execute (/home/node/node_modules/mysql2/lib/commands/command.js:29:26)
todo-api  |       at Connection.handlePacket (/home/node/node_modules/mysql2/lib/connection.js:488:32)
todo-api  |       at PacketParser.onPacket (/home/node/node_modules/mysql2/lib/connection.js:94:12)
todo-api  |       at PacketParser.executeStart (/home/node/node_modules/mysql2/lib/packet_parser.js:75:16)
todo-api  |       at Socket.<anonymous> (/home/node/node_modules/mysql2/lib/connection.js:101:25)
todo-api  |       at Socket.emit (node:events:513:28)
todo-api  |       at addChunk (node:internal/streams/readable:324:12)
todo-api  |       at readableAddChunk (node:internal/streams/readable:297:9)
todo-api  |       at Readable.push (node:internal/streams/readable:234:10) {
todo-api  |     code: 'ER_NO_SUCH_TABLE',
todo-api  |     errno: 1146,
todo-api  |     sqlState: '42S02',
todo-api  |     sqlMessage: "Table 'todo.tasks' doesn't exist",
todo-api  |     sql: 'CREATE TABLE IF NOT EXISTS `Tasks` (`id` INTEGER NOT NULL auto_increment , `name` VARCHAR(255) NOT NULL, `completed` TINYINT(1) NOT NULL, `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB;',
todo-api  |     parameters: undefined
todo-api  |   },
todo-api  |   original: Error: Table 'todo.tasks' doesn't exist
todo-api  |       at Packet.asError (/home/node/node_modules/mysql2/lib/packets/packet.js:728:17)
todo-api  |       at Query.execute (/home/node/node_modules/mysql2/lib/commands/command.js:29:26)
todo-api  |       at Connection.handlePacket (/home/node/node_modules/mysql2/lib/connection.js:488:32)
todo-api  |       at PacketParser.onPacket (/home/node/node_modules/mysql2/lib/connection.js:94:12)
todo-api  |       at PacketParser.executeStart (/home/node/node_modules/mysql2/lib/packet_parser.js:75:16)
todo-api  |       at Socket.<anonymous> (/home/node/node_modules/mysql2/lib/connection.js:101:25)
todo-api  |       at Socket.emit (node:events:513:28)
todo-api  |       at addChunk (node:internal/streams/readable:324:12)
todo-api  |       at readableAddChunk (node:internal/streams/readable:297:9)
todo-api  |       at Readable.push (node:internal/streams/readable:234:10) {
todo-api  |     code: 'ER_NO_SUCH_TABLE',
todo-api  |     errno: 1146,
todo-api  |     sqlState: '42S02',
todo-api  |     sqlMessage: "Table 'todo.tasks' doesn't exist",
todo-api  |     sql: 'CREATE TABLE IF NOT EXISTS `Tasks` (`id` INTEGER NOT NULL auto_increment , `name` VARCHAR(255) NOT NULL, `completed` TINYINT(1) NOT NULL, `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB;',
todo-api  |     parameters: undefined
todo-api  |   },
todo-api  |   sql: 'CREATE TABLE IF NOT EXISTS `Tasks` (`id` INTEGER NOT NULL auto_increment , `name` VARCHAR(255) NOT NULL, `completed` TINYINT(1) NOT NULL, `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB;',
todo-api  |   parameters: {}
todo-api  | }
確認したこと
エラーを見ると今からデータベースのテーブルを作成する関数を実行しようとしているのにテーブルがないと言われている。
todo.tasks doesn't existはtodoというデータベースの中のtasksというテーブルはないということ。
君はそのtasksを作るための関数ではないのか...?
解決策
原因はわかっていないが、Modelの定義の際にテーブル名を明示することでテーブルを作成することができた。
const Task = sequelize.define('Task', {
    name: {
        type: DataTypes.STRING,
        allowNull: false
    },
    completed: {
        type: DataTypes.BOOLEAN,
        allowNull: false
    }
},{
    tableName: "tasks"
});
Sequelizeには予測機能のようなものがあり、
sequelize.defineで定義した'Task'というものからテーブル名はこれを複数形にしたtasksが自動的にテーブル名として設定される。これを明示しただけなのだがエラーが出なくなった。
補足
これを確認したのちにテーブルを一度削除。テーブル名を設定する
},{
    tableName: "tasks"
});
の記述を消して再度実行してみると普通に動作した。原因は完全にわかっていないがMySQL側の問題ぽい?