Lambda Function cannot find relative .graphql schema file

Hello, and thank you in advance for reading this!

I’m making a mock, rudimentary Allrecipes-like website using a REST API. My server and client both use Apollo GraphQL and TypeScript. My client uses React.

The GitHub repository for my Apollo GraphQL server is here.

My server is using Apollo GraphQL, TypeScript, and a GraphQL schema specified in a .graphql file. My server basically only fetches data from the REST API and processes it, but this is intentional: I wanted to start with something simple before doing something more complicated with mutations and/or subscriptions.

Issue:

The Lambda Function cannot find the file that contains my GraphQL schema; Error during invocation: Error: ENOENT: no such file or directory, open '/graphql/schema.graphql'.

My question is: why is this error happening, and how can I address this while keeping my GraphQL schema in its own .graphql file? Is there an easier way to deploy my server while maintaining this?

This is a personal project and the local server works fine, so this is not an urgent problem – if I really need to demo my project, I can just use ngrok, but I would love to have the website hosted in all its glory on Netlify!

I also noticed that people who had similar problems were using JavaScript, so I hope the solution to my problem may prove useful to anyone who is using TypeScript and is in a similar position.

Issues that Looked Similar to Mine

I’m guessing the solutions to these issues did not work for me because I have been using netlify-lambda to build my function in TypeScript into a JavaScript file that I then deploy. I am guessing that somewhere in this process, the path to my schema file becomes broken. Naively placing my GraphQL schema file with its folder next to the JavaScript file does not work, so it also looks like the final deployment step may just be flat out ignoring that file.

Background Information:

I am working on deploying an Apollo GraphQL server to Netlify using apollo-server-lambda. This is my first major project using Apollo GraphQL, so I’m deploying my server and client separately because that is easier for me to handle right now.

My server is written in TypeScript so that my server is fully typed, and I have my GraphQL schema in its own file at <projectRoot>/graphql/schema.graphql as the single source of truth for the shape of the data, as opposed to having it all in a gql-tagged template in a single graphql.js file or several such files.

To deploy my server to Netlify, I followed these two tutorials:

^ This one showed how I can set up the code for the Lambda Function without affecting my local server.

^ This one showed how I can use Babel to convert my TypeScript code into JavaScript, but after some further research it appears as though this step is not necessary? I can just run netlify-lambda serve lambda/delish-api to serve my TypeScript code directly, for instance - although this does not solve my issue.

The deployment pipeline for my server:

  1. Copy the local server code into lambda/delish-api/bundle.
  2. Copy the GraphQL schema into lambda/delish-api/graphql.
  3. Run netlify-lambda build lambda/delish-api, using lambda/delish-api/delish-api.ts as the entry-point for the Lambda Function. netlify-lambda builds the function to functions/delish-api.js.
  4. The GitHub repository is connected to Netlify, so all I need to do is force a deploy on the website or via the Netlify CLI.

My server works normally when it is running locally: that is, the server starts up, I can load localhost:4000, and I will get the GraphiQL IDE, and I can query the GraphQL server.

However, when I deploy the Lambda Function (either locally or to Netlify) and go to localhost:9000/.netlify/functions/delish-api, the Lambda Function reports that it is unable to find the schema file.

I tried the answer linked here from the second post, but adding that to my server.ts for loading the schema path did not fix my issue. Currently, using that solution, I am loading my schema this way in server.ts:

const typeDefsPath =
  (process.env.LAMBDA_TASK_ROOT)
    ? path.resolve(process.env.LAMBDA_TASK_ROOT, config.lambda.schemaPath)
    : path.resolve(__dirname, config.local.schemaPath)

const typeDefs = readFileSync(typeDefsPath).toString()

where config is, in config.ts:

export default {
  local: {
    schemaPath: '../graphql/schema.graphql',
    graphqlDir: '../graphql'
  },
  lambda: {
    schemaPath: './graphql/schema.graphql',
    graphqlDir: './graphql'
  }
}

However, the choice of path does not make a difference - if I just the local path in both cases, I get the same error.

Thank you for reading this :grin: If you have any idea about how I can solve this issue, please let me know. I will be happy to provide any additional information as well.

Hiya and sorry to hear about the trouble! I am curious if you are intending the lambda to read from your site’s deployed files, rather than from a file deployed with the function? For the lambda paths starting with “/” are not “from the root of your website”, for instance - they are “from the root of what was shipped with your lambda”.

I think though you are trying instead to get the file into the function, right? And to guide you in doing so, I would have linked you to a comment in one of the posts you linked above: Hosting a file along with my function - #23 by Dennis . But I think you’ve maybe tried that already? Sorry to not be a pro in most of the technologies (typescript, functions, graphql) you use to be better able to understand your very detailed (thank you!) post in full.

Hello I have the same problem as willowell and went through the same and other tutorials, examples and so on. All of them don’t work (anymore?).

My typeDef.ts looks like this (Typescript can now run without compilation on Netlify, yay!)

import { join } from "path";

import { readFileSync } from "fs";

export default readFileSync(join(__dirname, "schema.graphql")).toString();

The index.ts looks like this

import { ApolloServer } from "apollo-server-lambda";
import { resolvers } from "./resolvers";
import typeDefs from "./typeDef";

const server = new ApolloServer({
    typeDefs,
    resolvers,
});

const handler = server.createHandler();

export { handler };

index.ts, schema.graphql and typeDef.ts sit in /functions/airtableApi/

When I start netlify dev I open the Playground on http://localhost:8888/.netlify/functions/airtableApi I get the following error

Error: ENOENT: no such file or directory, open '/Users/devatrox/Projekte/ev-travel-history-api/.netlify/functions-serve/airtableApi/src/airtableApi/schema.graphql'
  Object.openSync (fs.js:461:3)
  readFileSync (fs.js:364:35)
  Object.<anonymous> (/Users/devatrox/Projekte/ev-travel-history-api/.netlify/functions-serve/airtableApi/src/airtableApi/index.js:57801:50)
  Module._compile (internal/modules/cjs/loader.js:1176:30)
  Object.Module._extensions..js (internal/modules/cjs/loader.js:1196:10)
  Module.load (internal/modules/cjs/loader.js:1040:32)
  Function.Module._load (internal/modules/cjs/loader.js:929:14)
  Module.require (internal/modules/cjs/loader.js:1080:19)
  require (internal/modules/cjs/helpers.js:72:18)
  Object.<anonymous> (/Users/devatrox/Projekte/ev-travel-history-api/.netlify/functions-serve/airtableApi/airtableApi.js:1:18)

Any idea how to get this working?

Hey there, @devatrox :wave:

It looks like this thread has been quiet for the past few days since you posted this. Sorry about that!

Are you still encountering this issue? If so, can you share any changes that have occurred in the past week, as well as your Netlify site name?

Hello,

thanks for getting back to it. No nothing has changed since I posted this. I don’t want to share my site name here so it’s not misused. I am also currently working more locally with netlify dev and did not deploy for a while.

Hey there, @devatrox

Thanks for following up! Unfortunately, I do not think we will be able to assist you further without some additional information so that we can view your site and your github repo.

If you feel comfortable, you can DM me that information. That being said, I will still have to share it with my team in order to look into this further. Let me know if you’re interested in that!

Hello @hillary,

Sorry I wasn’t responding, I didn’t have time to work on this until now.
I created a test repo to illustrate the problem. The netlify site name is festive-curran-b99121 and the repo on Github is at GitHub - devatrox/netlify-test with a description on what’s going on.

Thanks!

Hey,

Did you have any luck solving this issue? I’m encountering the same.

I did try to use the include_files config option but I had no luck with that - File-based configuration | Netlify Docs

Hi folks,
Could you please try creating a [functions] block in your netlify.toml and adding node_bundler = "esbuild"? We don’t have native typescript support for functions using our default function bundler, but esbuild does. Here are our docs on this: Build functions | Netlify Docs

Let us know if that helps!