Google-api-nodejs-client: UnhandledPromiseRejectionWarning: Error: error:0906D06C:PEM routines:PEM_read_bio:no start line

Created on 9 Apr 2018  ·  21Comments  ·  Source: googleapis/google-api-nodejs-client

I get the above error when I try initializing the drive with the jwt token. Below's my implementation.
the keys are valid and I downloaded the file from the google developer console.

...
const jwtClient = new google.auth.JWT({                                          
  email: secret.client_email,                                                    
  key: secret.private_key,                                                       
  scopes                                                                         
})                                                                               

const drive = google.drive({                                                     
  version: 'v3',                                                                 
  auth: jwtClient                                                                
})   

function workspace () {                                                          
  return new Promise(async (resolve, reject) => {                                
    const folder = await findFolder(workDir)                                     
    if (folder) return resolve(folder)                                           
     return createFolder(workDir)                                                 
       .then(({ data }) => resolve(data))                                         
        .catch(err => reject(err))                                                 
   })                                                                             
} 
...

const cwd = await workspace()
console.log(cwd)

workDir is a variable holding a reference to a string with the name of a working directory.

The weird thing is that this was working last week but then it stopped working for some reason.

needs more info

Most helpful comment

i was using .env as well and this problem happened to me. To fix, I just had to wrap the value in the .env file in double quotes. Hope it helps someone.

NODE_ENV=production
API_KEY=abc
GOOGLE_API_KEY="-----BEGIN PRIVATE ... asdfasdf\n-----END PRIVATE KEY-----\n"

(edit) the other thing that just happened when going to prod was that something between the ENV var setting and the app replaced all \n with \\n, so i just had to do:

googleApiKey = _.replace(process.env.GOOGLE_API_KEY, new RegExp("\\\\n", "\g"), "\n")

All 21 comments

So I doubt this is the problem, but I am guessing you can simplify your workspace function like this 😄

async function workspace () {                                                          
  const folder = await findFolder(workDir);
  if (folder) {
    return folder;
  }
  return createFolder(workDir);
} 

Now onto the error. This often happens when you accidentally provide the wrong kind of key. Please be 100% sure that secret.private_key contains the data you'd expect to see by doing a console.log(secret) at the top. My guess is that either a.) it's returning empty for some reason or b.) you're accidentally passing a public key.

Please try this stuff and let me know how it goes!

haha, thanks @JustinBeckwith. I'll definitely refactor that code. This is an example of the json file I get from google developer console:

{
  "type": "service_account",
  "project_id": "",
  "private_key_id": "",
  "private_key": "",
  "client_email": "",
  "client_id": "",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://accounts.google.com/o/oauth2/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": ""
}

I use the private_key as it is provided. Perhaps because I'm using dotenv to load it from an .env file?

Let me know if this sounds right.

I know this is a silly question.... the actual private_key_id you get back isn't blank ... is it? If you're doing something with dotenv, I'd suggest you're super sure what's getting passed into your objects :)

At runtime, add a console.log(secrets) right before you load em up. Feel free to twiddle the values a bit as not to expose your keys, but do that and paste the result here :)

haha @JustinBeckwith yeah, definitely not blank. There's a weird behavior with dotenv and multi-line secrets. We all know this :D. I'll give it another try.

It seems to be working though. It's one of those strange errors that goes away once you restart your computer. I'll go ahead and close this ticket. Thanks again @JustinBeckwith

Happy it's working 🎉

Hey @JustinBeck, reopened this because it doesn't work as expected in production. JWT auth works just fine though locally. Am I missing something?
screen shot 2018-04-25 at 11 59 07 am

This happens when you have an invalid PEM. Typically it means that the path to your keyfile is wrong :)

I'm using an env variable like so:

const { google } = require('googleapis')

const config = require('../config')

const { secret, scopes } = config.google

const jwtClient = new google.auth.JWT({
  email: secret.client_email,
  key: secret.private_key,
  scopes
})

const drive = google.drive({
  version: 'v3',
  auth: jwtClient
})
...

you can find the entire file here

What's in your secret.private_key variable? Can you console.log that and twiddle a few chars and post it?

the private key I generated for the service account from google dev console.

Just to be 100% sure - does it look mostly like this?

-----BEGIN PRIVATE KEY-----\nMEIE9....

Also, double check with a console.log IN PRODUCTION :)

It does look like that when I output it locally.

I'll give logging in production a try.

Hey @pauldariye - is this still a problem? One thought I had - if this is working locally but not in the cloud, it either means a.) you have an env var mixup problem, or b.) there may be a mismatch of your local npm modules vs what's installed in your cloud environment.

I would try doing a rm -rf node_modules, npm install, and see if it still works locally.

In the meantime - it's been a week since I heard anything here, and as far as I can tell we don't have a bug. If you can provide a repo here, I'd be happy to open the issue again :)

i was using .env as well and this problem happened to me. To fix, I just had to wrap the value in the .env file in double quotes. Hope it helps someone.

NODE_ENV=production
API_KEY=abc
GOOGLE_API_KEY="-----BEGIN PRIVATE ... asdfasdf\n-----END PRIVATE KEY-----\n"

(edit) the other thing that just happened when going to prod was that something between the ENV var setting and the app replaced all \n with \\n, so i just had to do:

googleApiKey = _.replace(process.env.GOOGLE_API_KEY, new RegExp("\\\\n", "\g"), "\n")

@JustinBeckwith need your assistance.
I got the same error as described on stackowerflow.
Google API auth via service key succeeds, but still gets “401 Login Required” on subsequent requests:
https://stackoverflow.com/questions/53125641/google-api-auth-via-service-key-succeeds-but-still-gets-401-login-required-on
My code:
const { google } = require('googleapis')
...
async getMessagesList () {
const scopes = [
'https://mail.google.com',
'https://www.googleapis.com/auth/gmail.compose',
'https://www.googleapis.com/auth/gmail.modify',
'https://www.googleapis.com/auth/gmail.readonly'
];
const jwtClient = new google.auth.JWT(key.client_email, null, key.private_key, scopes, '[email protected]', key.project_id, key.private_key_id);
jwtClient.authorize((err, response) => {
console.log(
'res', response
)
//
// Here I got in console { access_token:
// 'ya29.GoQBVgYBno...',
// token_type: 'Bearer',
// expiry_date: 1542359137000,
// id_token: undefined,
// refresh_token: 'jwt-placeholder' }
//
gmail.users.threads.list(
{ userId: 'me', auth: response.access_token },
(res) => {
console.log('list', res)
}
)
})

If I pass inside gmail.users.threads.list { userId: 'me', auth: jwtClient } then here
console.log('list', res) I got "list null" but I already have 4 letters in my google g suite email account...

GOOGLE_API_KEY="-----BEGIN PRIVATE ... BLAH\n-----END PRIVATE KEY-----\n"

Same Problem and this worked for me .... and thanks everyone :)
it obviously expects the quotation mark to be included.

anyways moving on to my next bug lol

@JustinBeckwith sorry.
The problem was in gmail.users.threads.list's callback arguments.
I passed only 'res' instead of 'error' and 'res'.
The working code is:
gmail.users.threads.list(
{ userId: 'me', auth: response.access_token },
(error, res) => {
console.log('list', res)
}
)

Awesome. Glad to hear it's all worked out!

i was using .env as well and this problem happened to me. To fix, I just had to wrap the value in the .env file in double quotes. Hope it helps someone.

NODE_ENV=production
API_KEY=abc
GOOGLE_API_KEY="-----BEGIN PRIVATE ... asdfasdf\n-----END PRIVATE KEY-----\n"

(edit) the other thing that just happened when going to prod was that something between the ENV var setting and the app replaced all \n with \\n, so i just had to do:

googleApiKey = _.replace(process.env.GOOGLE_API_KEY, new RegExp("\\\\n", "\g"), "\n")

THANK YOU!

Using Azure DevOps pipelines with App Settings variable injections, you will run in to the same issue with API keys. They add an extra ** to all **\n in the key. @bradwbradw hit the nail on the head with the solution.

My end result:
const privateKey = process.env.GSUITE_PRIVATE_KEY.replace(new RegExp('\\\\n', '\g'), '\n')

Was this page helpful?
0 / 5 - 0 ratings