Search code examples
javascriptnode.jssqlitediscord.jssequelize.js

Why do I get `no such table` even though I created the model?


I don't understand why I get Error: SQLITE_ERROR: no such table: cities even though I created the model with Sequelize. I followed the same code that worked fine last time.
models/cities.js:

const { Sequelize, DataTypes } = require('sequelize');

const db = new Sequelize({
    dialect: 'sqlite',
    storage: './database.sqlite',
});

const Cities = db.define('cities', {
    userId: {
        type: DataTypes.STRING,
        unique: true,
        primaryKey: true,
        allowNull: false,
    },
    name: {
        type: DataTypes.STRING,
        allowNull: false,
    },
    // ...
    busStationsBuilt: {
        type: DataTypes.INTEGER,
        allowNull: false,
        defaultValue: 0,
    },
});

module.exports = { Cities };

db-init.js (run manually):

const { Sequelize } = require('sequelize');

const db = new Sequelize({
    dialect: 'sqlite',
    storage: './database.sqlite',
});

require('./models/cities.js');

const force = process.argv.includes('--force') || process.argv.includes('-f');

db.sync({ force }).then(async () => {
    console.log('Database synced.');

    db.close();
}).catch(console.error);

commands/found.js:

const { Cities } = require('../models/cities.js');
const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');

module.exports = {
    data: new SlashCommandBuilder()
        .setName('found')
        .setDescription('Found your city!')
        .addStringOption(option =>
            option
                .setName('name')
                .setDescription('The name of your city!')
                .setRequired(true)
        ),
    async execute(interaction) {
        const name = interaction.options.getString('name');

        const cityAlreadyExists = await Cities.findOne({ where: { userId: interaction.user.id } });

        if (!cityAlreadyExists) {
            try {
                const city = await Cities.create({
                    userId: interaction.user.id,
                    name: name,
                });

                const cityEmbed = new EmbedBuilder()
                    .setColor(0x73a0d0)
                    .setTitle(city.name)
                    .setDescription('Here are your city\'s stats:')
                    .addFields(
                        { name: '๐Ÿ˜„ Happiness:', value: city.happiness },
                        { name: '๐Ÿง Population:', value: city.population },
                        { name: '๐Ÿ’ต Balance:', value: city.balance },
                        { name: '๐Ÿชจ Resources:', value: city.resources },
                        { name: '๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ Crowdedness:', value: city.crowdedness },
                        { name: '๐Ÿš— Traffic:', value: city.traffic },
                        { name: '๐Ÿ›ข๏ธ Pollution:', value: city.pollution },
                    );

                return interaction.reply({ content: 'Your city has been created!', embeds: [cityEmbed] });
            } catch (error) {
                await interaction.reply({ content: 'An error occurred while creating your city. Support server: https://discord.gg/XuZNNJbf4U', ephemeral: true });
                return console.error(error);
            }
        } else {
            return interaction.reply('Your city already exists!');
        }
    }
}

I've asked similar questions and everything worked fine then so I'm not sure what went wrong this time. There are no issues/errors when I run db-init.js but I get the error when I run /found.


Solution

  • It looks like you are probably creating multiple databases because the storage path variable is relative to the file where you're creating the Sequelize db:

    const db = new Sequelize({
        dialect: 'sqlite',
        storage: './database.sqlite',
    });
    

    I suggest you use an absolute path to your sqlite db file. Check out this answer for some help on getting path info in node.js.