Next.js Discord

Discord Forum

Instrumentation hook doesn't appear to have access to server-side modules

Answered
Clapper Rail posted this in #help-forum
Open in Discord
Clapper RailOP
I'm trying to implement an instrumentation hook that sets up some regular tasks (using node-cron), but on server startup an error is thrown:

 ⨯ ./node_modules/node-cron/src/background-scheduled-task/index.js:3:16
Module not found: Can't resolve 'child_process'
  1 | const EventEmitter = require('events');
  2 | const path = require('path');
> 3 | const { fork } = require('child_process');
    |                ^
  4 | const uuid = require('uuid');
  5 |
  6 | const daemonPath = `${__dirname}/daemon.js`;


(it was unable to resolve 'path' before, but I hacked around that by installing the path module myself, then realized that was silly)

Not really sure what's happening here, these modules should be available, but I think maybe it's assuming it should be executing the hook in a client-side context, and therefore native node modules like path and child_process aren't allowed? Not really sure here. Everything I've found searching for the error so far has been people trying to require the path module in frontend code, but (as far as I know) that's not what I'm doing here.
Answered by Clapper Rail
Hmm, from digging through the code I'm starting to think the issue is that it's using the Edge runtime, and therefore doesn't have access to native node APIs.
View full answer

11 Replies

Clapper RailOP
Hmm, actually, I tried copying that line (const path = require('path'); ) into my instrumentation.ts file, and it seems to work fine
...but, it's not a bug in the node-cron module as far as I can tell, because I can require that from the nodejs REPL just fine
Clapper RailOP
Also, after starting the server (and ignoring the error, for now), trying to access pages on the site then also reports that same error, meaning instrumentation.ts is being reloaded?
Clapper RailOP
Hmm, interestingly, at a glance anyway, it seems like the server is trying to compile the file outside of the instrumentation hook code path? If it were throwing this error in loadInstrumentationModule(), I'd expect it to throw the error with the string "An error occurred while loading instrumentation hook:", but it doesn't
And before throwing the error the server says "Compiling /instrumentation" which may be an indication that it thinks the file is something else for some reason?
Clapper RailOP
Searching deep into the archives yields this post: https://nextjs-forum.com/post/1151677129482846228

...which seems to indicate that my initial assumption was correct, that instrumentation.ts is loaded as a client-side module, so doesn't have access to path or child_process, but that question was closed despite the fact that this is (in my view) a bug
Clapper RailOP
I also tried adding 'use server'; to the instrumentation.ts file, to no avail.
Clapper RailOP
Hmm, from digging through the code I'm starting to think the issue is that it's using the Edge runtime, and therefore doesn't have access to native node APIs.
Answer
Clapper RailOP
(but of course, this is not documented, or I would've figured it out hours ago)
Aha, there is documentation saying it runs in "all environments" which is annoying, but ultimately I guess I was wrong about it not being documented.
Clapper RailOP
For curious folks who find this later: You (like me) probably didn't read the full documentation for the instrumentation hook, which includes this section:

https://nextjs.org/docs/app/building-your-application/optimizing/instrumentation#importing-runtime-specific-code

...which reads, in relevant part:

Next.js calls register in all environments, so it's important to conditionally import any code that doesn't support specific runtimes (e.g. Edge or Node.js).

...and the following code example:

export async function register() {
  if (process.env.NEXT_RUNTIME === 'nodejs') {
    await import('./instrumentation-node')
  }
 
  if (process.env.NEXT_RUNTIME === 'edge') {
    await import('./instrumentation-edge')
  }
}


Hopefully that helps any folks coming after me 🙂