Firebase, like any tool, required specific versions and oddly enough it has NOT caught up to being fully compatible (out of the box) with Node version 22 (or higher).
The specific issue is if you try to run (and emulate / deploy) a Firebas nodeJS webapp after getting all the core items setup properly you will possibly get the following error:
TypeError: Cannot read properties of undefined (reading 'getTime')
at Responder.provider (/Users/<username_here>/.nvm/versions/node/v22.0.0/lib/node_modules/firebase-tools/node_modules/superstatic/lib/providers/fs.js:89:38)
You can also read about this issue on GitHub:
Thankfully the solve is simple, though it is a manual fix ... or better to say, work-around.
Source Of The Issue
Simply put: the superstatic
library wants to get the current time in milliseconds, thought he way it asks for it is not the same way the current version of Node does the stat
time object.
Previous, the stat
object had the mTime
attribute, and that itself was an object that get the function getTime()
. Presently, mTime
is a value and not an object.
The solution
You need to modify your computers (or deployment's) fs.js
file in the superstatis
module.
For me, the file path was:
/Users/<username_here>/.nvm/versions/node/v22.0.0/lib/node_modules/firebase-tools/node_modules/superstatic/lib/providers/fs.js
So you, it might be more similar to:
/usr/local/lib/node_modules/firebase-tools/node_modules/superstatic/lib/providers/fs.js
Either way, find that file for your current Node install, and edit that file!
vim /Users/<username_here>/.nvm/versions/node/v22.0.0/lib/node_modules/firebase-tools/node_modules/superstatic/lib/providers/fs.js
Go to the line in question, in my case it was line 89. There you will find a try-catch statement and you'll find the root cause .. the return statement uses the getTime() function:
modified: stat.mtime.getTime(),
So all we do is change it to:
modified: stat.mtimeMs,
The stat
object has mTime-like values, one of which is mtimeMs
which is the required millisecond
time that getTime
used to return.
Thus the return statement looks like:
return {
modified: stat.mtimeMs,
size: stat.size,
etag: await fetchEtag(stat.pathname, stat),
stream: fs.createReadStream(stat.pathname),
};
Save, recompile. And re-run / re-deploy and like magic it works again!