Can a lambda function read included_files directly from the file system? "Ask Netlify" suggests I can

I have a lambda function that’s attempts to retrieve HTML from netlify/functions/content. Here’s a picture:

I’ve tried several included_files paths for courses:

  [functions."courses"] 
    included_files = ["./content/*/*.html"] // or ["content/**/*.html"], etc.

An attempted read in courses.js is as follows:
const readingPath = path.join(process.cwd(), 'netlify', 'functions', section.readingContent);

Where section.readingContent is “./content/distress/section1_reading.html”
(also tried it without the ./)

The error I see is:

Jul 17, 03:04:06 PM: 37f90d3c ERROR  Error reading content for section 1: Error: ENOENT: no such file or directory, open '/var/task/netlify/functions/content/distress/section1_reading.html'
    at Object.readFileSync (node:fs:442:20)
    at /var/task/netlify/functions/courses.js:83:51
    at Array.map (<anonymous>)
    at Runtime.handler (/var/task/netlify/functions/courses.js:78:25)
    at Runtime.handleOnceNonStreaming (file:///var/runtime/index.mjs:1205:29) {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: '/var/task/netlify/functions/content/distress/section1_reading.html'
}

I’ve tried the more direct approach, namely:
const readingHtml = fs.readFileSync(section.readingContent, 'utf8');

which results in a different error:

Jul 17, 03:20:40 PM: 87341890 ERROR  Error reading content for section 1: Error: ENOENT: no such file or directory, open './content/distress/section1_reading.html'
    at Object.readFileSync (node:fs:442:20)
    at /var/task/netlify/functions/courses.js:80:51
    at Array.map (<anonymous>)
    at Runtime.handler (/var/task/netlify/functions/courses.js:78:25)
    at Runtime.handleOnceNonStreaming (file:///var/runtime/index.mjs:1205:29) {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: './content/distress/section1_reading.html'
}

That last approach looks identical to what Ask Netlify suggests:

Yes, you can access files specified in the included_files property from the file system within your Netlify Function. When you use the included_files configuration in your netlify.toml (or equivalent configuration), Netlify bundles those files with your function during deployment. This means they are available at runtime in the deployed function’s file system, and you can read them using standard Node.js file system methods like fs.readFileSync.

For example, if you include a file or directory like this:

[functions]
  included_files = ["assets/*.pdf"]

You can then access those files in your function code:

const { readFileSync } = require("fs");
const fileContent = readFileSync("./assets/example.pdf");

This approach is necessary because serverless functions do not have access to the full project file system or CDN-deployed files—only to what is bundled with the function itself. The included_files property ensures the files you need are present in the function’s execution environment see documentation and official support answer.

If you do not specify a file in included_files and it is not statically required or imported, it will not be available to your function at runtime.

It could be that I’m misunderstanding what this blog post is saying:

# ... or only JSON files in "function-1"
[functions."function-1"]
  included_files = ["languages/**.json"]

Does “function-1” refer to a function name, or a folder? It’s the latter, what good is it if there are multiple functions with different dependencies? It wouldn’t serve to limit the dependencies at all.

Yes, you can.
I suspect that the paths just aren’t correct.

The documentation:
https://docs.netlify.com/build/configure-builds/file-based-configuration/#functions

Says:

included_files: list of additional paths to include in the function bundle. Although our build system includes statically referenced files (like require("./some-file.js") ) by default, included_files lets you specify additional files or directories and reference them dynamically in function code. You can use * to match any character or prefix an entry with ! to exclude files. Paths are absolute paths relative to the base directory.

It looks like you have the files at netlify/functions/content/

But the included_files specifies content/

Your Base directory is probably the default, which would be the root of your repository.

You could try moving the files, or changing the included_files to something like:
netlify/functions/content/*/*.html

Amusingly, the answer that the AI references as an “official support answer” is one of mine.
It’s not even remotely official, I don’t work for Netlify.

Thanks for the link, which didn’t turn up in my searches. I had (wrongly) assumed that the paths were relative to the functions folder, so I’ll give another shot.

That link also suggests that the quoted part of the functions selector is supposed to match a function name, which I would hope limits the amount of data loaded on the INIT phase of lambda invocation.

Let’s see how far I can get, now.

Success! Thank you very much.