Demo, all content is generated
Question

Build passes but the deployed function says ENOENT for a JSON file I read with fs

Solved · 331 views · asked by santi_dev_wannabe · edited

My route handler reads a list of postcodes from a JSON file:

const file = path.join(process.cwd(), "data", "postcodes.json");
const postcodes = JSON.parse(await fs.readFile(file, "utf8"));

Locally fine. On Vercel the route returns 500 and the logs say:

Error: ENOENT: no such file or directory, open '/var/task/data/postcodes.json'

The file is in the repo, I checked on GitHub.

What I’ve tried

Moved the file to /public, then it worked on one route but not on another. Cursor suggested vercel.json includeFiles but I don't know the syntax for Next.

Comment
Is the data folder in .gitignore or .vercelignore by any chance? anjali_p · edited
no, it's in the repo, I can see it on GitHub santi_dev_wannabe · edited

3 answers

Marked as helpful by the asker
deploydan · edited

Vercel only packs the files it can trace from your imports into each function. A path you build at runtime with path.join and read with fs is invisible to that tracing, so the file isn't in the function bundle.

Simplest fix: import it, then it's part of the bundle and you don't need fs at all:

import postcodes from "@/data/postcodes.json";

If you really need to read files at runtime (many files, or a format you can't import), tell Next to include them:

// next.config.js
module.exports = {
  outputFileTracingIncludes: {
    "/api/postcodes": ["./data/**/*"],
  },
};

Don't rely on /public for this. Those files go to the CDN, not reliably into your functions.

Comment
import it is. 2 lines. and I understand why it worked locally now, my laptop has every file santi_dev_wannabe · edited
mei_lin · edited

One caveat with the import: the JSON becomes part of your function bundle. For a postcode list of a few MB that's fine. If it grows to tens of MB, put it in your database instead, you'll probably want to query it by prefix at some point anyway.

Comment
It's about 400 KB, so fine for now. Good to know where the line is. santi_dev_wannabe · edited
nils_tw · edited

Note for anyone copying from older blog posts: outputFileTracingIncludes used to live under experimental in next.config. In Next 15 and later it's top-level.

Comment