Unlock seamless workflows and faster delivery with our latest releases - Join the deep dive

Lambda function not returning properly in Netlify

10 replies
Last updated: Jun 10, 2020
Hey folks! Bit of a random code question that I thought I might throw out there – Not Sanity related hence not in the 'Help" channel, but I need someone to bounce this off of, and this is probably the most engaged and helpful community of devs I know, so I thought it was probably worth posting here:
I’ve never had this issue before - A lambda function which completes its tasks, makes its requests and those requests return properly, but the lambda fails to return back to the calling function. The offending lambda function is as follows:

import axios from 'axios'

import { getAuth0AccessToken } from '../lib/getAuth0AccessToken'

exports.handler = async event => {
  if (!event.body) {
    return {
      statusCode: 400,
      body: JSON.stringify({
        statusCode: 400,
        message: 'Bad request',
      }),
    }
  }
  try {
    const { email, password } = JSON.parse(event.body)
    console.log('Hello from createAccount! payload -->', event.body)

    const response = await getAuth0AccessToken()
    const token = await response.access_token
    // console.log('Access token returned. Proceeding to create user...\nToken -->', token)
    const createUserObj = {
      email: email,
      password: password,
      connection: process.env.AUTH0_DB,
    }
    console.log('Object being sent to create user api --> ', JSON.stringify(createUserObj))

    const userResponse = await <http://axios.post|axios.post>(`${process.env.AUTH0_AUDIENCE}users`, createUserObj, {
      headers: {
        Authorization: `Bearer ${token}`,
        'Content-Type': 'application/json',
      },
    })
    const user = userResponse.data
    console.log('User has been returned! -->', user)

    return {
      statusCode: 200,
      body: JSON.stringify(user),
      headers: { 'content-type': 'application/json' },
    }
  } catch (err) {
    let statusCode
    let message
    if (err.response) {
      statusCode = err.response.data.statusCode
      message = err.response.data.message
    } else {
      statusCode = 500
      message = 'Unknown error in Auth0 request'
    }
    console.log(`${statusCode} error from Auth0 --> ${message}`)
    return {
      statusCode,
      body: JSON.stringify({
        statusCode,
        message,
      }),
      headers: { 'content-type': 'application/json' },
    }
  }
}
The last console.log() logs out fine, with the user object that comes back from Auth0, totally as expected. The return statement, however, doesn’t seem to fire - The calling function client-side is as follows:

import axios from 'axios'

export const createAccount = async payload => {
  try {
    const response = await <http://axios.post|axios.post>('/.netlify/functions/createAccount', JSON.stringify(payload))
    console.log('Netlify function has returned! Data -->', response.data)
    return response.data
  } catch (err) {
    console.log('Error has been returned to API!', err)
    return new Error(err)
  }
}
The log here after the 
<http://axios.post|axios.post>()
 to my lambda function never fires. Instead the XHR request just sits as a pending promise and then fails out when it reaches the timeout. Its the same if the request to Auth0 returns an error – The error is thrown and caught properly, and the log in the lambda function fires, but the request to the lambda function just sits open, rather than being returned and resolved with the error.
Admittedly, I’m not an expert in lambda functions, and I’ve only recently started using them in async mode, but from a pure JS mode, this doesn’t seem to make any sense to me. All the awaited items have completed, the previous statement has completed properly, so the return statement should fire.
I assume I must be missing something, and it’s probably something obvious. I don’t have anyone to bounce these things off nowadays, though… So does anyone have any ideas?

Cheers
👍
Jun 8, 2020, 12:54 PM
I'm not sure about this, but in my lambda functions on Netlify I use the callback pattern:
exports.handler = async function (event, context, callback) {
    callback(null, {
      statusCode: 200,
      headers,
      body: ''
    })
}
Perhaps you need to employ something like that?
Jun 8, 2020, 1:01 PM
If you're not using the
callback
pattern, I think you need to
resolve
the async function in order for it to return something
exports.handler = async event => {
  return new Promise(async function(resolve, reject) { 
   resolve({
        statusCode: 200,
        headers,
        body: 'something'
      })
  }
}
Jun 8, 2020, 1:05 PM
This is from the top of my head, so take it with a grain of salt etc
Jun 8, 2020, 1:08 PM
Thanks,
user J
– I'll take a look at that. Its weird - I used the same pattern I am using here on our own website to scale some images, but I guess as they were returned directly to the browser, rather than being called from and returning to JS, that might be the difference
Jun 8, 2020, 1:17 PM
Huh. Weirdly, using the callback pattern, even with async, works in this case.
Jun 8, 2020, 1:32 PM
Welp, I guess that sorts that then... Callbacks it is!
Jun 8, 2020, 1:32 PM
Thanks for taking a look
Jun 8, 2020, 1:32 PM
👍
Jun 8, 2020, 2:07 PM
You can avoid using the callback pattern if you serverless function is marked as async.
user M
I’d be really interested to learn more about how you’re using Auth0 and your experience with it btw. I’ve been doing a lot of work with protecting serverless functions recently
Jun 10, 2020, 2:20 AM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?