'cloudinary error: must supply api-key - /node_modules/cloudinary/lib/utils.js:982

I am using cloudinary to upload photos on my webpage. I have added a new function to the webpage ( facebook login) and now the cloudinary throw an error when I try to upload a photo like before.

"/home/ubuntu/workspace/YelpCamp/node_modules/cloudinary/lib/utils.js:982 throw "Must supply api_key"; ^ Must supply api_key"

The API_KEY, API_SECRET and the CLOUD_NAME are saved in a .env file, and these are correct.

var express = require("express");
var router  = express.Router();
var Campground = require("../models/campground");
var middleware = require('../middleware') ;          //because of the index.js default name
var geocoder = require('geocoder');

///////////////////////////////////////
// MULTER

var multer = require('multer');
var storage = multer.diskStorage({
  filename: function(req, file, callback) {
    callback(null, Date.now() + file.originalname);
  }
});
var imageFilter = function (req, file, cb) {
    // accept image files only
    if (!file.originalname.match(/\.(jpg|jpeg|png|gif)$/i)) {
        return cb(new Error('Only image files are allowed!'), false);
    }
    cb(null, true);
};
var upload = multer({ storage: storage, fileFilter: imageFilter});

///////////////////////////////////////
//CLOUDINARY

var cloudinary = require('cloudinary');
cloudinary.config({ 
  cloud_name: process.env.CLOUD_NAME, 
  api_key: process.env.CLOUD_KEY,
  api_secret: process.env.CLOUD_SECRET
});





router.post('/', middleware.isLoggedIn, upload.single('image'), function(req, res) {
    console.log(req.user);
    //GEOCODER
    geocoder.geocode(req.body.location, function (err, data) {              
        
    //CLOUDINARY UPLOAD   
         cloudinary.uploader.upload(req.file.path, function(result) {           
                 var image = {
                     path: result.secure_url,
                     id: result.public_id
                 };
                 
                 
                 var name = req.body.name;
                 var price = req.body.price;
                 var description = req.body.description;
                 if(req.user.facebook.username) {
                     var username = req.user.facebook.username;
                 } else {
                     username = req.user.local.username;
                 }
                 var author = {
                    id: req.user._id,
                    username: username
                };
               if(!data.results[0]) {
                    var lat = 90;
                    var lng = 0;
                    var location = "North Pole";
                   
               } else {
                 lat = data.results[0].geometry.location.lat;
                 lng = data.results[0].geometry.location.lng;
                 location = data.results[0].formatted_address;
               }
                
                var newCampground = {name: name, price: price, image: image, description: description, author: author, location: location, lat: lat, lng: lng};
          //create      
            Campground.create(newCampground, function(err, result) {
             if(err) {
                 console.log(err);
             } else {
                 console.log(result);
                 res.redirect('/campgrounds');
             }
             
            });  
        });
    });
});
<% include ../partials/header %>







    <div class="row">
        <h1 style="text-align: center;">Create a New CampGround</h1>
        <div style='width: 30%; margin: 30px auto;'>
            <form action='/campgrounds' method='POST' enctype="multipart/form-data">
                <div class='form-group'>
                    <label for="name">Name</label>
                    <input class="form-control" id="name" type='text' name='name' placeholder='Name'>
                </div>
                 <div class='form-group'>
                     <label for="price">Price</label>
                    <input class="form-control" id="price" type='number' name='price' placeholder='price' min="0.01" step="0.01">
                </div>
                <div class='form-group'>
                    <label for="image">Image</label>
                    <input type="file" id="image" name="image" accept="image/*" required>
                </div>
                <div class='form-group'>
                    <label for="description">Description</label>
                    <input class="form-control" id="description" type='text' name='description' placeholder='Write description'>
                </div>
                <div class="form-group">
                    <label for="location">Location</label>
                    <input class="form-control" type="text" name="location" id="location" placeholder="Yosemite National Park, CA">
                </div>
                <div class='form-group'>
                    <button class="btn btn-lg btn-default btn-primary btn-block">Submit!</button>
                </div>
            </form>
            <a href="/campgrounds"> Go Back </a>
        </div>
        
    </div>






<% include ../partials/footer %>


Solution 1:[1]

The cloudinary config values must be in strings otherwise they won't work. Configure your code either of these ways in your cloudinary segment:

1a: CloudinaryConfig.js:

cloudinary.config({ 
    cloud_name: process.env.CLOUD_NAME, 
    api_key: process.env.CLOUD_KEY,
    api_secret: process.env.CLOUD_SECRET
});

1b: .env

   CLOUDINARY_CLOUD_NAME='sample'
   CLOUDINARY_API_KEY='874837483274837'
   CLOUDINARY_API_SECRET='a676b67565c6767a6767d6767f676fe1'

2: Putting your cloudinary-supplied values directly into the code:

   cloudinary.config({ 
       cloud_name: 'sample', 
       api_key: '874837483274837',
       api_secret: 'a676b67565c6767a6767d6767f676fe1'
   });

NOTE: Ensure that you don't expose your config values for security reasons. If you're committing code to a public repo like github, use .gitignore to leave out whatever file where you store your secret info.

Checkout the cloudinary docs for more reference: https://cloudinary.com/documentation/node_integration.

Solution 2:[2]

The reason can be your js file where you would have not included require('dotenv').config(); Try adding this and then run your code.

Solution 3:[3]

Can you try putting the API key directly in your code and see if that works. You could also add a print statement and see what response you get for API key

Solution 4:[4]

The dotenv must be required up top where you are using your process.env.API_KEY:

require("dotenv").config();

Solution 5:[5]

If you're using a NodeJS server-side function to upload, ensure you've installed the dotenv package;

yarn add dotenv

Thereafter, put the cloudinary variables in a '.env' file. From the file (controller) where you're to make the upload, you must point to dotenv, to that file, relative to where your package.json file is sitting. Here's an instance for me, trying to make an upload from 'CompanyControllers.ts'

import dotenv from "dotenv";
dotenv.config({path: "./backend/src/settings/controllers/CompanyControllers.ts"});

So, if I do;

console.log("\n\t Cloud name: ", process.env.CLOUDINARY_UPLOAD_CLOUD_NAME)
.....my cloudinary cloud name is logged
const cloudinaryResponse = await cloudinary.v2.uploader.upload(filePath, {
            cloud_name: process.env.CLOUDINARY_UPLOAD_CLOUD_NAME, 
            api_secret: process.env.CLOUDINARY_UPLOAD_API_SECRET, 
            upload_preset: process.env.CLOUDINARY_UPLOAD_PRESET_NAME,
            api_key: process.env.CLOUDINARY_UPLOAD_API_KEY,
            resource_type: "image",
            secure: true
        });

Solution 6:[6]

use this

const dotenv = require('dotenv'); dotenv.config();

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 adiga
Solution 2 Manoj
Solution 3 Aditi Madan
Solution 4 unixb0y
Solution 5 Chukwunazaekpere
Solution 6 Abhishek Dulat