How to Fix SequelizeDatabaseError: Relation 'users' Does Not Exist – A Beginner's Guide

If you’re new to Sequelize (a popular ORM for Node.js) and working with databases like PostgreSQL, MySQL, or SQLite, you might have encountered the frustrating error: SequelizeDatabaseError: Relation 'users' does not exist. This error occurs when Sequelize tries to interact with a database table (in this case, users), but the table doesn’t actually exist in your database.

Don’t worry—this is a common issue, especially for beginners, and it’s usually fixable with a few simple checks. In this guide, we’ll break down what causes this error, walk through step-by-step solutions, and share tips to prevent it in the future. By the end, you’ll understand how Sequelize models, migrations, and database tables work together.

Table of Contents#

  1. Understanding the Error
  2. Common Causes of the Error
  3. Step-by-Step Fixes
  4. Prevention Tips to Avoid Future Errors
  5. Conclusion
  6. References

Understanding the Error#

First, let’s demystify the error message:

  • "Relation": In database terms (especially PostgreSQL), a "relation" refers to a table, view, or other database object. So "relation 'users' does not exist" simply means the users table is missing.
  • Why Sequelize Throws This: Sequelize acts as a bridge between your Node.js code and the database. When you define a model (e.g., a User model) and try to query it (e.g., User.findAll()), Sequelize expects a corresponding table (users) to exist in the database. If it doesn’t, you get this error.

Common Causes of the Error#

Before diving into fixes, let’s identify the most likely culprits:

1. Migrations Were Never Run#

Migrations are scripts that create or modify database tables. If you defined a User model but never ran the migration to create the users table, the table won’t exist.

2. Model-Table Name Mismatch#

Sequelize models often map to database tables, but if the model’s expected table name doesn’t match the actual table name in the database, Sequelize will look for a non-existent table.

3. Incorrect Database Connection#

If Sequelize is connected to the wrong database (e.g., a staging database instead of your local development database), the users table might exist in one DB but not the one you’re connected to.

4. model.sync() Was Not Called (or Misconfigured)#

In development, model.sync() can auto-create tables from models. If you forgot to call sync() or used the wrong options (e.g., force: false), the table might not be created.

5. Case Sensitivity Issues#

Some databases (e.g., PostgreSQL on Linux) are case-sensitive. If your model references Users (capital "U") but the table is named users (lowercase), Sequelize will fail to find it.

Step-by-Step Fixes#

Let’s tackle each cause with actionable solutions.

3.1 Verify Your Database Connection#

First, confirm Sequelize is connected to the correct database.

How to Check:#

  1. Locate your Sequelize configuration file (usually config/config.json or config/database.js).
  2. Check the development (or relevant environment) settings to ensure the database name, username, and password are correct.

Example config.json:

{
  "development": {
    "username": "your_db_username",
    "password": "your_db_password",
    "database": "your_dev_database_name", // Ensure this is the DB you intend to use
    "host": "localhost",
    "dialect": "postgres" // or "mysql", "sqlite", etc.
  }
}
  1. Test the connection with Sequelize’s authenticate() method:
// In your database setup file (e.g., db.js)
const { Sequelize } = require('sequelize');
const sequelize = new Sequelize(
  'your_dev_database_name', // from config
  'your_db_username', 
  'your_db_password', 
  { host: 'localhost', dialect: 'postgres' }
);
 
// Test the connection
async function checkConnection() {
  try {
    await sequelize.authenticate();
    console.log('✅ Connected to the correct database!');
  } catch (error) {
    console.error('❌ Failed to connect:', error);
  }
}
checkConnection();

If the connection fails, fix your config.json credentials. If it succeeds but the error persists, move to the next step.

3.2 Check if the 'users' Table Actually Exists#

Even if you’re connected to the right database, the users table might not exist. Let’s verify:

For PostgreSQL Users:#

  • Open a terminal and connect to your database:
    psql -U your_db_username -d your_dev_database_name
  • List all tables with:
    \dt
    This will show a list of tables. If users isn’t in the list, the table is missing.

For MySQL Users:#

  • Connect to your database:
    mysql -u your_db_username -p your_dev_database_name
  • List tables with:
    SHOW TABLES;

For SQLite Users:#

  • SQLite uses a file-based database. Check if the table exists with:
    sqlite3 your_database_file.db "SELECT name FROM sqlite_master WHERE type='table' AND name='users';"
    If no output is returned, the table is missing.

3.3 Ensure Migrations Are Created and Run#

Migrations are the recommended way to create tables (avoid manual SQL!). If the users table is missing, you likely forgot to create or run the migration.

Step 1: Create a Migration (If None Exists)#

Use the Sequelize CLI to generate a migration for the users table:

npx sequelize-cli model:generate --name User --attributes name:string,email:string

This creates two files:

  • A model file: models/user.js
  • A migration file: migrations/XXXXXX-create-user.js (where XXXXXX is a timestamp).

Step 2: Review the Migration File#

Open the migration file (e.g., migrations/20240101000000-create-user.js). It should look like this:

'use strict';
 
module.exports = {
  up: async (queryInterface, Sequelize) => {
    // Creates the "users" table
    await queryInterface.createTable('users', { // Table name here!
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      name: {
        type: Sequelize.STRING
      },
      email: {
        type: Sequelize.STRING,
        unique: true
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
  },
  down: async (queryInterface, Sequelize) => {
    // Rolls back the migration (drops the table)
    await queryInterface.dropTable('users');
  }
};

Key Check: Ensure the createTable argument is 'users' (not 'user' or another name).

Step 3: Run the Migration#

Execute the migration to create the users table:

npx sequelize-cli db:migrate

You should see output like:

== 20240101000000-create-user: migrating =======
== 20240101000000-create-user: migrated (0.012s)

Now recheck for the users table (using \dt in PostgreSQL or SHOW TABLES in MySQL). It should exist!

3.4 Fix Model-Table Name Mismatches#

Sequelize models default to pluralizing the model name for the table. For example:

  • Model name: User → Default table name: users (pluralized).

But if your migration uses a different table name (e.g., user instead of users), or your model explicitly sets a different tableName, you’ll get a mismatch.

Example of a Mismatch:#

  • Model: Explicitly sets tableName: 'user'
    // models/user.js
    module.exports = (sequelize, DataTypes) => {
      const User = sequelize.define('User', {
        name: DataTypes.STRING,
        email: DataTypes.STRING
      }, {
        tableName: 'user' // Explicit table name (singular)
      });
      return User;
    };
  • Migration: Creates users (plural)
    await queryInterface.createTable('users', { ... }); // Table name is "users"

Result: Sequelize looks for user (from the model) but the migration created users → error!

Fix: Align Model and Migration Table Names#

Ensure the model’s tableName matches the migration’s createTable name. For example:

// models/user.js (fixed)
module.exports = (sequelize, DataTypes) => {
  const User = sequelize.define('User', {
    name: DataTypes.STRING,
    email: DataTypes.STRING
  }, {
    tableName: 'users' // Matches migration's table name
  });
  return User;
};

3.5 Use model.sync() (For Development Only)#

In development, you can use model.sync() to auto-create tables from models (instead of migrations). This is faster for prototyping but not recommended for production (it can drop data!).

How to Use sync():#

Call sequelize.sync() (to sync all models) or User.sync() (to sync only the User model) after defining your models:

// In your app setup (e.g., app.js)
const User = require('./models/user');
 
// Sync all models (creates tables if they don't exist)
async function syncModels() {
  await sequelize.sync({ force: true }); // "force: true" drops tables first (use with caution!)
  console.log('✅ Tables synced!');
}
syncModels();
  • force: true: Drops existing tables and recreates them (use in dev to reset schema).
  • alter: true: Updates tables to match models (safer than force but still not for production).

3.6 Resolve Case Sensitivity Issues#

Databases like PostgreSQL (on Linux) or SQL Server are case-sensitive for table names. For example:

  • If your model uses tableName: 'Users' (capital "U"), but the migration creates users (lowercase), Sequelize will throw "relation 'Users' does not exist".

Fix: Match Case Exactly#

Ensure the model’s tableName and migration’s createTable name use the same case:

// models/user.js
{
  tableName: 'users' // Lowercase, matches migration
}
 
// Migration
await queryInterface.createTable('users', { ... }); // Lowercase

Prevention Tips to Avoid Future Errors#

Now that you’ve fixed the error, here’s how to prevent it from happening again:

  1. Always Run Migrations: Get in the habit of running npx sequelize-cli db:migrate after creating/updating models.
  2. Version-Control Migrations: Never edit old migrations (they’re history!). Instead, create new migrations to modify tables.
  3. Avoid sync() in Production: Migrations are safer for production—sync() can accidentally drop data.
  4. Test Migrations Locally: Always run migrations on your local machine first to catch errors before deploying.
  5. Check Model-Table Mappings: Double-check that tableName in models matches migration table names.

Conclusion#

The SequelizeDatabaseError: Relation 'users' does not exist error is a common hurdle for beginners, but it’s easily fixed by checking migrations, model-table mappings, and database connections. Remember: migrations are your best friend for managing database schema changes, and sync() is only for development!

By following the steps in this guide, you’ll not only fix the error but also gain a better understanding of how Sequelize, models, and databases work together.

References#