useRelativePaths fails to resolve paths when the application is started outside the project folder in production
Prerequisites
- [x] I have written a descriptive issue title
- [x] I have searched existing issues to ensure the bug has not already been reported
Fastify version
5.6.1
Plugin version
8.2.0
Node.js version
22.17.0
Operating system
Linux
Operating system version (i.e. 20.04, 11.3, 10)
12
Description
When running the application in production mode from a directory other than the project root — for example:
NODE_ENV=production node ./project-folder/server.js
Returns the error: No client distribution bundle found.
— the application throws the following error when I use a custom outDir:
TypeError [ERR_INVALID_ARG_TYPE]: The "paths[0]" argument must be of type string. Received undefined
Link to code that reproduces the bug
https://github.com/lucasfernandodev/fastify-vite-bug/
Expected Behavior
Vite should start normally even when the command is executed from a different directory.
Thanks for the repro. I'm able to see the problem as well.
The reason this is happening is because in order for useRelativePaths to work, we need to find the files based on process.cwd(). If you start from outside the directory, it will not work.
If you really want to start from outside the directory, using absolute paths is the way to go.
Do you really feel we need to support starting with relative paths from outside the directory?
The application where I’m encountering the error is a CLI that needs to be executable from any directory. Users may run the binary globally, so assuming process.cwd() as the project root isn’t always valid.
Without using the useRelativePaths option, the absolute paths defined in the build file are usually those from GitHub Actions.
I am confused by this part:
Without using the
useRelativePathsoption, the absolute paths defined in the build file are usually those from GitHub Actions.
The useRelativePaths option controls whether the paths you provide in your vite.config file get transformed into relative paths or not. I don't think they have anything to do with GitHub Actions.
I was referring to the proposal to use absolute paths (I assumed it was to disable the useRelativePaths option). Without using useRelativePaths during the build, the generated vite.config.json file contains the absolute paths of the build environment (for example, the CI runner workspace / GitHub Actions).
Example of the generated file:
{
"base": "/",
"root": "/home/user/project/package/fastify-vite-bug/client",
"build": {
"assetsDir": "assets",
"outDir": "/home/user/project/package/fastify-vite-bug/bin/client"
},
"fastify": {
"outDirs": {
"client": "/home/user/project/package/fastify-vite-bug/bin/client"
},
"entryPaths": {}
}
}
I have a project for a command-line tool. Since the package is built and then added to npm, for Vite to work correctly, useRelativePaths needs to support relative paths outside the directory.
I see. In that case the only thing I can think of to fix this is to add an option to the fastify plugin that tells it where to find the vite.config.json file in your bin directory. Happy to review a PR.
I can try to solve this problem, but it will probably take a while (Junior Dev).
I was working on the error demonstration project directly from node_modules to understand the code, and I made some simple modifications that apparently resolved all the errors I tested. Would it be simpler to implement a new option for the vite.config.json path? Or the modifications below.
Updates:
Create a function to identify the folder where the application is running:
function getCurrentExecutionFileDirectory() {
const entryFile = (require.main && require.main.filename) || process.argv[1];
return resolve(dirname(resolve(entryFile)))
}
Change the initial search folder for package-directory:
const { packageDirectory } = await import('package-directory');
outDirRoot = await packageDirectory({ cwd: getCurrentExecutionFileDirectory() })
Improve resolveIfRelative function to return absolute path without using cwd when root and path are relative:
async function resolveIfRelative(p, root) {
if (isAbsolute(p)) {
return p
}
if (isAbsolute(root)) {
return resolve(root, p)
}
const { packageDirectory } = await import('package-directory');
const outDirRoot = await packageDirectory({ cwd: getCurrentExecutionFileDirectory() })
const target = resolve(outDirRoot, root, p);
return target
}
Adding the option to use distDir instead of root (path):
function resolveRoot(distDir, path) {
let root = path;
if (root.startsWith("file:")) {
root = fileURLToPath(root);
}
if (!exists(root)) {
root = distDir;
}
if (stat(root).isFile()) {
root = dirname(root);
}
return root;
}
It is passing the current tests: https://github.com/lucasfernandodev/fastify-vite/tree/improve-relative-path-resolution