You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

部署Node.js到Heroku时遭遇MongoNotConnectedError问题求助

问题:React+Express+Mongoose项目部署Heroku时出现MongoNotConnectedError

我做了一个React前端、Express Node.js后端(搭配Mongoose与MongoDB)的项目,本地运行正常,但构建后部署到Heroku时出现应用错误。

后端连接代码

require('dotenv').config();
const express = require('express')
const session = require("express-session")
const bodyParser = require('body-parser')
const cors = require('cors')
const zomatoRoutes = require('./Routes/zomato')
const paymentRoutes = require('./Routes/payments')
const mongoose = require('mongoose')
const passport = require("passport")
const MongoStore = require('connect-mongo');


const uri = process.env.MONGO_URI || 'mongodb://localhost/zomato';

console.log(uri,'this is the mongo Atlas uri if connected using that !!!')

const options = {
    useNewUrlParser: true,
    useUnifiedTopology: true,
    dbName:'zomato1'
}

const connectDB = async () => {

    await mongoose.connect(uri, options ).then(() => {
        console.log('mongo connected')
    }).catch( e => console.log(e))
}


connectDB().then(() => {
    
    app.listen( process.env.PORT ||5252 , () => {
        console.log("express app is up and running on port 5252");
    })
})

Mongo会话存储配置

app.use(session({
    secret: "this is unambigous secret",
    resave: false,
    saveUninitialized: false,
    cookie: { maxAge: 24*60*60*1000 },
    store   : MongoStore.create({ 
        client: mongoose.connection.getClient(),
        dbName:'zomato1',
        ttl: 14 * 24 * 60 * 60
     })
    
}));

app.use(passport.initialize());
app.use(passport.session());

部署错误日志

执行git push heroku master:main部署时,出现MongoNotConnectedError: MongoClient must be connected to perform this operation错误,完整日志如下:

mongodb+srv://vishal_torne_22:********@db-first-hernode.zu6btrs.mongodb.net/<DBNamecomeshere>?retryWrites=true&w=majority this is the mongo Atlas uri if connected using that !!!
2022-07-31T11:19:34.581869+00:00 app[web.1]: /app/node_modules/mongodb/lib/utils.js:367
2022-07-31T11:19:34.581876+00:00 app[web.1]: throw new error_1.MongoNotConnectedError('MongoClient must be connected to perform this operation');
2022-07-31T11:19:34.581877+00:00 app[web.1]: ^
2022-07-31T11:19:34.581877+00:00 app[web.1]:
2022-07-31T11:19:34.581878+00:00 app[web.1]: MongoNotConnectedError: MongoClient must be connected to perform this operation
2022-07-31T11:19:34.581878+00:00 app[web.1]: at getTopology (/app/node_modules/mongodb/lib/utils.js:367:11)
2022-07-31T11:19:34.581881+00:00 app[web.1]: at Collection.createIndex (/app/node_modules/mongodb/lib/collection.js:258:82)
2022-07-31T11:19:34.581881+00:00 app[web.1]: at MongoStore.setAutoRemove (/app/node_modules/connect-mongo/build/main/lib/MongoStore.js:147:35)
2022-07-31T11:19:34.581881+00:00 app[web.1]: at /app/node_modules/connect-mongo/build/main/lib/MongoStore.js:128:24
2022-07-31T11:19:34.581882+00:00 app[web.1]: at processTicksAndRejections (node:internal/process/task_queues:96:5)
2022-07-31T11:19:34.581882+00:00 app[web.1]:
2022-07-31T11:19:34.581882+00:00 app[web.1]: Node.js v17.9.1
2022-07-31T11:19:34.703486+00:00 heroku[web.1]: Process exited with status 1
2022-07-31T11:19:34.791551+00:00 heroku[web.1]: State changed from starting to crashed

疑问与已尝试方法

疑问

  • Heroku 20栈是否必须使用MongoClient?
  • 为何本地正常的Mongoose.connect()部署后会报错?

已尝试的解决方法

  • 在MongoDB Atlas中添加白名单0.0.0.0/0(包含当前IP)
  • 将Mongoose连接代码改为异步,确保先连接数据库再启动服务
  • 修改package.json中的引擎版本以适配Heroku:
{
"version": "1.0.0",
  "engines": {
    "node": "17.x",
    "npm":"8.x"
  }
}

解决方案

问题根源

错误出在MongoStore初始化时机过早——你在Mongoose完成数据库连接之前就创建了MongoStore实例,此时mongoose.connection.getClient()返回的客户端还未建立连接,导致MongoStore尝试操作数据库时触发MongoNotConnectedError。

本地运行正常是因为本地数据库连接速度快,可能在MongoStore初始化前连接已完成;但Heroku环境下网络延迟更高,连接建立速度慢,就暴露了这个时序问题。另外,Heroku 20栈并没有强制要求使用MongoClient,问题和栈版本无关。

修复步骤

  1. 调整MongoStore的初始化时机
    不要在全局直接创建MongoStore,而是等Mongoose连接完成后再初始化session中间件:

    // 先定义app和其他基础中间件
    const app = express();
    app.use(bodyParser.json());
    app.use(cors());
    // ...其他非session相关中间件
    
    const connectDB = async () => {
        try {
            await mongoose.connect(uri, options);
            console.log('mongo connected');
            // 连接成功后再初始化session和MongoStore
            app.use(session({
                secret: "this is unambigous secret",
                resave: false,
                saveUninitialized: false,
                cookie: { maxAge: 24*60*60*1000 },
                store: MongoStore.create({ 
                    client: mongoose.connection.getClient(),
                    dbName:'zomato1',
                    ttl: 14 * 24 * 60 * 60
                })
            }));
            app.use(passport.initialize());
            app.use(passport.session());
    
            // 挂载路由
            app.use('/api', zomatoRoutes);
            app.use('/api', paymentRoutes);
    
            // 启动服务
            app.listen(process.env.PORT || 5252, () => {
                console.log(`express app is up and running on port ${process.env.PORT || 5252}`);
            });
        } catch (e) {
            console.error('MongoDB连接失败:', e);
            process.exit(1);
        }
    };
    
    connectDB();
    
  2. 优化Mongoose连接逻辑
    你的connectDB函数混用了await和.then(),统一改为try/catch写法,更清晰且便于错误处理。

  3. 验证Heroku环境变量
    确保Heroku的环境变量MONGO_URI正确配置,且URI中的数据库名称和dbName参数一致(你的URI里写了<DBNamecomeshere>,需要替换为实际的数据库名zomato1)。

额外建议

  • 避免在Heroku使用Node.js 17.x版本,该版本属于不稳定版本,建议切换到LTS版本(比如16.x),减少兼容性问题:
    "engines": {
      "node": "16.x",
      "npm": "8.x"
    }
    
  • 在MongoDB Atlas中,建议只添加Heroku的出站IP段或使用VPC peering,而不是直接开放0.0.0.0/0,提升安全性。

内容的提问来源于stack exchange,提问作者Vishal Torne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 17:57:25