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.
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
.