Issue with deploy function using Netlify API

Hi there,

I’m trying to create a website with a function using digest deploys with API.
(I’m following this doc Get started with the Netlify API | Netlify Docs)

I can successfully deploy a site without a function, but I want to deploy with a function.

I send the request to create the site with the following payload:

{
    "async": true,
    "files": {
        "/404/index.html": "0f23c546eedb3821696491c99cc955223cbf22c9",
        "/Fruits/index.html": "eda72f7b881defd80c9e961d39f82179313ba533",
        "/ContactUs/index.html": "23277c62408f72dc4d208ae39ad217622f85ba26",
        "/ContactUs/styles.css": "771d57c349a57c1250ba7bd52e05f6539031034c",
        "/Fruits/styles.css": "596aec9e20a7b605b5bffe31bd86abc3059246c6",
        "/content/gauva.svg": "4ec20616d6778f026d5b541324ef1482cdb410f6",
        "/content/grapes.svg": "85bd194386db7b610949b6528af185d9be09b27d",
        "/content/twitter-with-circle.svg": "c43c452e2a2dc721cb9dd6b1bd4b163cd16b8155",
        "/content/linkedin-with-circle.svg": "efd6708f9be4bf30e3d7fbc083e3c406ef8b3cee",
        "/404/styles.css": "a7c341616f92d229783dc376d0a16ad24403065c",
        "/content/facebook-with-circle.svg": "af6b52dce28ed554eba8420e35cc8a5bef5095e6",
        "/content/orange.png": "462886f2a997ef65c7eee0b22db32818da0ee88b",
        "/content/tasty-image.png": "0886762caaf315d5728d17605b69ec2b917d6861",
        "/content/а.svg": "050a1274cad58270bb1933fc9f3cd91e38bb6713",
        "/content/grapes.png": "294150ecd3ee303240499bbc167f1867f4b2decf",
        "/content/slide-img.png": "2848f848090e85c1fe57b82c32c312f6237aaf9d",
        ...etc...
    },
    "functions": {
        "publisher": "a5c7586429a434a3c54fee2b382c484482311769"
    }
}

The function was zipped with the following structure

publisher/publisher.js => publisher.zip

I calculated the SHA for publisher.zip => “a5c7586429a434a3c54fee2b382c484482311769”

Function code (simple as possible):

exports.handler = function (event, context, callback) {
  callback(null, {
    statusCode: 200,
    body: "Hello, World",
  });
};

After creating the site, I send the request to upload publisher.zip file content
PUT to https://api.netlify.com/api/v1/deploys/${deployId}/files/functions/publisher.zip
response like:

{
    id: 'functions/publisher.zip'
    mime_type: 'application/zip'
    path: 'functions/publisher.zip'
    sha: 'a5c7586429a434a3c54fee2b382c484482311769'
    size: 253
}

I see the site and function in the dashboard UI

But then I try to check created function I get the Invalid request message in logs:

If I try to open deployed function I see 500 error

Is it possible to get more detailed logs to better understand what is wrong with my function?
My netlify app is https://scintillating-licorice-606074.netlify.app

(I also tried to upload the function as a file but got the same result. Please check Netlify App )

Thanks

That sounds like about what I’d do if I were going to manually upload functions;
don’t see any obvious bugs in your thinking.

While I can see a few more logs than you can, they say something like “function not found” with a bunch of internal identifiers. I’ll have to file an issue for our devs to take a look at, but I cannot tell what exactly is happening (I do think your upload is fine; we do some parsing at upload time & I don’t see errors about invalid zipfile format which was my first guess) - so we’ll need some folks who understand how all the things are connected to help us figure out what the fix could be.

Could you tell us more about your use case that you’d do this upload manually, rather than via our CLI? Would be a lot easier to do that way and I bet you’d be able to run it in the same ways you’d use our API, only we’d take care of a lot more of the details around uploading for you and it would probably “just work”.

Hi @fool,

I’m working on SaaS and can’t use CLI on the server.
I want to create a site with a function that can re-generate this site.

I’m planning the following:

  1. I have the pre-generated static site and function in storage. I create the site and deploy static content and function.
  2. Then I change the metadata for this site in the editor and store it in FaunaDB.
  3. To apply these changes I need to run deployed function to re-generate and redeploy the site. For this functionality, I’m planning to use the background function that I can run with a POST request from our dashboard. This publishing function will get metadata from FaunaDB, generate new static content in the storage, and deploy it to the site.

It would be nice if you can provide step-by-step instructions (API requests) on how to deploy the site and function(better for background function) using Netlify API.

This is why we don’t recommend double posting @igor.o. It might make you think you’ll get faster and better support, but in reality, it’s the opposite. In your other post, I ended up telling you to use CLI, and now I discover this where you mention CLI is not an option.

In any case, I believe the problem is occuring because you’re directly converting the function from .js to .zip. You need to bundle all dependencies and produce a single JS file and then zip it, or produce a folder in which you’d have all your required Node Modules and dependencies which you can then zip.

We do not have any guides for this, but that’s the general way. The easier way would be to store the pre-made site and Function in a Git repo and deploy using that.

@hrishikesh as I mention the function before what dependencies do you see in this function or do you have specific requirements for zip file structure or js file content and bundling?

It would be nice if you can provide step-by-step instructions (API requests) on how to deploy the site and function(better for background function) using this Netlify API.
By providing this example you will reduce the number of questions about this API.

I decided to create this dedicated question because it was in post 10 months old and nobody replied to the comment that you mentioned.

By doing so, we had to answer 2 threads instead of 1 - which is exactly what slows us down, especially when there are so many users who do so. I’m not trying to say you did anything wrong, it’s a rational thinking that old posts won’t get answered, but on Netlify, we reach out to each and every unanswered post.

This Function syntax is outdated and no longer recommended.

Try changing it to:

exports.handler = async function(event, context) {
  return {
    body: 'Hello world',
    statusCode: 200
  }
}

This function should be easily bundled by just creating a zip which would include this JS file. That’s what the CLI does. There’s no bundling required apart from zipping it.

Here’s the package that Netlify uses to zip the functions: @netlify/zip-it-and-ship-it - npm

If you can’t run the CLI, maybe you can use this to generate your zips easily.

That’s the only tricky part about deploying functions via API. The uploading part should be fairly straightforward.

Hi @hrishikesh

Thank you for the quick reply.

I tried the function you recommended

zipped it with npm you recommended

using simple NodeJs code

import { zipFunctions } from ‘@netlify/zip-it-and-ship-it’;
const result = await zipFunctions(‘./in’, ‘./out’);

but have the same error result:
The site was successfully deployed and the function has the same error
you can check it (https://jade-brioche-dd643c.netlify.app)

Hi @igor.o,

We checked the deployed function and as far as I can see, there appears to be something else going on, which I don’t think is related to Function bundling. Most likely the bundling is working fine, but it’s the uploading that somehow acting weird.

We’ve filed this for the developers to look at and would follow up once we’ve more info.

Hi @hrishikesh

Do you have any ETA when I could get any details about my issue?

Thanks

Hey @igor.o,

Unfortunately, no ETA as such. As far as I can see, this issue has popped some internal discussion soon after it was filed. So, there would be activity on it, possibly in the following week. We’ll keep you posted on how that goes.

Hi @hrishikesh
Gentle ping.
Any progress on this issue?

Hey there, @igor.o :wave:

Thanks for following up! We don’t have an update for you at this time. Sorry I don’t have better news! We will follow up on this thread when we have more information for you.

Hey @igor.o,

After a deeper investigation, it turns out that, you were hitting the files endpoint to upload the function, something like:

https://api.netlify.com/api/v1/deploys/${deployId}/files/functions/publisher.zip

however, the correct one to deploy a function is:

https://api.netlify.com/api/v1/deploys/{deploy_id}/functions/publisher?runtime=js

It turns out that, we’ve a bug that allowed the file to upload and marked the deploy as completed even though the function was actually never uploaded, but in the meantime, if you try the second URL, it should work. Could you try that please?

Hi @hrishikesh

Thank you for the details, I will try and post the results here.

As I understand from

https://api.netlify.com/api/v1/deploys/{deploy_id}/functions/publisher?runtime=js

publisher here is the file name for publisher.zip without extension?

Yes, that is correct. This is also mentioned in the docs: Get started with the Netlify API | Netlify Docs

1 Like

@hrishikesh
Now I’m getting the error

“Uploaded file publisher did not match deploy”

It looks like I’m doing something wrong with SHA.
Now I zip publisher.js to publisher.zip and calculate SHA for publisher.zip

I have a question regarding SHA calculation.

What SHA are you expecting on function upload?
Should I calculate SHA on publisher.js file and send it on site create, and before upload, zip it to send in the deploy request?
Or I should zip publisher.js to publisher.zip and calculate SHA for publisher.zip?

It’s not clear from docs.

Not sure, I’d try both and let us know how it goes in each case! This is not something people do very often so we don’t have a good answer but should be an easy experiment for you to do :wink:

In case neither works, please share how you generate the SHA and we’ll ask our developers for their insight.

Hi @fool

I tried both and every time gets the same error:

Uploaded file publisher did not match deploy
statusCode: 422
statusText: 'Unprocessable Entity'

To generate SHA I use the following function in NodeJS:

calculateSha1(data: NodeJS.ReadableStream): Promise<string> {
        const hash = crypto.createHash("sha1").setEncoding('hex');
        return new Promise((resolve, reject) => data.on('error', reject)
            .pipe(hash)
            .once('finish', () => resolve(hash.read()))
        );
 }

I use this function for site files deployment and it works but for functions, it doesn’t.
I also changed the header from
Content-Type: application/octet-stream
To
Content-Type: application/zip

And set request["body"] = body where body type is Uint8Array

Send PUT to https://api.netlify.com/api/v1/deploys/{deploy_id}/functions/publisher?runtime=js

Could you please check the logs for the following sites in my account to clarify what I’m doing wrong:

  • Deployment for the site with the publisher function (created publisher.zip → calculated SHA for publisher.zip file → send content in body)
    Site ID: 3e22dbfa-82f9-4407-a2fd-2870dcf4ca4a

  • Deployment for the site with the publisher function (calculated SHA for publisher.js → created publisher.zip → send content in body)
    Site ID: d7aff202-5807-4c4e-90a6-9de26e07c44e

I have paid plan, can I get the responses faster if I submit a support request Support (netlify.com)?

Hey @igor.o,

Sorry for the delay! It appears that our docs are a little incomplete on this and we’ve filed this for docs team to update it, but meanwhile, would you be able to try with SHA256 instead of SHA1? Functions need Sha256 while other files need SHA1.

@hrishikesh thank you
Will try and let you know