others-How to solve 'expect a string but got undefined' issue when using dotenv in js or javascript applications ?

1. Purpose

In this post, I would demo how to solve the below issue when dotenv in js or javascript application.

[nodemon] 1.18.7
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `node src/index.js`

/Users/bswen/js-projects/jsew-notedly/api/node_modules/mongoose/lib/connection.js:541
    throw new MongooseError('The `uri` parameter to `openUri()` must be a ' +
    ^
Error [MongooseError]: The `uri` parameter to `openUri()` must be a string, got "undefined". Make sure the first parameter to `mongoose.connect()` or `mongoose.createConnection()` is a string.
    at new MongooseError (/Users/bswen/js-projects/jsew-notedly/api/node_modules/mongoose/lib/error/mongooseError.js:10:11)
    at NativeConnection.Connection.openUri (/Users/bswen/js-projects/jsew-notedly/api/node_modules/mongoose/lib/connection.js:541:11)
    at Mongoose.connect (/Users/bswen/js-projects/jsew-notedly/api/node_modules/mongoose/lib/index.js:328:15)
    at Object.connect (/Users/bswen/js-projects/jsew-notedly/api/src/db.js:9:14)
    at Object.<anonymous> (/Users/bswen/js-projects/jsew-notedly/api/src/index.js:10:4)
    at Module._compile (internal/modules/cjs/loader.js:959:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10)
    at Module.load (internal/modules/cjs/loader.js:815:32)
    at Function.Module._load (internal/modules/cjs/loader.js:727:14)
    at Function.Module.runMain (internal/modules/cjs/loader.js:1047:10)
    at internal/main/run_main_module.js:17:11 {
  message: 'The `uri` parameter to `openUri()` must be a string, got "undefined". Make sure the first parameter to `mongoose.connect()` or `mongoose.createConnection()` is a string.',
  name: 'MongooseError'
}
[nodemon] app crashed - waiting for file changes before starting...

The core error is:

Error [MongooseError]: The `uri` parameter to `openUri()` must be a string, got "undefined". Make sure the first parameter to `mongoose.connect()` or `mongoose.createConnection()` is a string.

But I have already configured the uri that used in the connection, just as follows:

DB_HOST=mongodb://10.3.1.2:27017/jset-notes

Why did this happen?

2. Environment

  • node.js
  • visual studio code

3. The problem and solution

3.1 The problem

I am coding to connect to a mongodb database from a node.js application.

image-20210719175659871

The configuration file is as follows, saved as file .env in the root directory of the project.

## Database
DB_HOST=mongodb://10.3.1.2:27017/jset-notes

And then the main code in index.js is as follows:


const DB_HOST = process.env.DB_HOST;

require('dotenv').config();
const db = require('./db');
db.connect(DB_HOST);

The package.json is as follows:

{
  "name": "notedly-api",
  "version": "1.0.0",
  "description": "API code examples for JavaScript Everywhere by Adam Scott, published by O'Reilly Media",
  "main": "src/index.js",
  "scripts": {
    "start": "nodemon src/index.js",
    "dev": "nodemon src/index.js",
  },
  "repository": {
    "type": "git",
    "url": "[email protected]:javascripteverywhere/api.git"
  },
  "nodemonConfig": {
    "ignore": [
      "**.test.js"
    ]
  },
  "keywords": [],
  "author": "Adam Scott",
  "license": "MIT",
  "dependencies": {
    "apollo-server-express": "2.4.0",
    "bcrypt": "3.0.6",
    "cors": "2.8.5",
    "dotenv": "6.1.0",
    "express": "4.16.4",
    "express-session": "1.15.6",
    "graphql": "^14.1.1",
    "graphql-depth-limit": "1.1.0",
    "graphql-iso-date": "3.6.1",
    "graphql-validation-complexity": "0.2.4",
    "helmet": "3.21.2",
    "jsonwebtoken": "8.5.1",
    "marked": "0.7.0",
    "md5": "2.2.1",
    "mongoose": "5.7.13",
    "nodemon": "1.18.7",
    "passport": "0.4.0",
    "passport-github2": "0.1.11"
  },
  "devDependencies": {
    "eslint": "5.13.0",
    "eslint-config-prettier": "4.0.0",
    "eslint-plugin-prettier": "3.0.1",
    "faker": "4.1.0",
    "node-fetch": "2.5.0",
    "prettier": "1.18.2"
  }
}

When run the below command:

$ npm run dev

We got the error:

Error [MongooseError]: The `uri` parameter to `openUri()` must be a string, got "undefined". Make sure the first parameter to `mongoose.connect()` or `mongoose.createConnection()` is a string.

Why?

3.2 The solution

We should ajust the code in index.js:

require('dotenv').config(); //this line should be executed at first

const DB_HOST = process.env.DB_HOST;

const db = require('./db');
db.connect(DB_HOST);

3.3 The theory

We are using dotenv to configure our application.

Dotenv is a zero-dependency module that loads environment variables from a .env file into process.env. Storing configuration in the environment separate from code is based on The Twelve-Factor App methodology.

As early as possible in your application, require and configure dotenv.

require('dotenv').config()

Create a .env file in the root directory of your project. Add environment-specific variables on new lines in the form of NAME=VALUE. For example:

DB_HOST=localhost
DB_USER=root
DB_PASS=s1mpl3

process.env now has the keys and values you defined in your .env file.

const db = require('db')
db.connect({
  host: process.env.DB_HOST,
  username: process.env.DB_USER,
  password: process.env.DB_PASS
})

4. Summary

In this post, I tried to demo how to solve the The uri parameter to openUri() must be a string, got "undefined" problem. The key point is to execute the require('dotenv').config() at first, then you can read the configuration from process.env .