Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error using miniflare -w; FetchError: No fetch handler after rebuild #34

Closed
TimTinkers opened this issue Aug 22, 2021 · 9 comments
Closed

Comments

@TimTinkers
Copy link

I am on Windows. While stumbling my way to the error in #33 I also encountered this issue with Miniflare failing on rebuild with the watcher. I am including logs that demonstrate starting my worker with miniflare -w, making a request to my worker which failed due to #33, then removing the problematic caching code. At this point the worker is rebuilt automatically. The call should succeed now. When I make another request to my worker, the call fails with FetchError: No fetch handler responded and unable to proxy request to upstream: no upstream specified. When I terminate Miniflare and restart it, the same call will succeed as expected. Here are my logs:

$ miniflare -w

up to date, audited 92 packages in 672ms

8 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

> file@1.0.0 build
> rm -rf ./dist && rollup -c


./src/main.mjs → ./dist/main.mjs...
created ./dist/main.mjs in 245ms
[mf:inf] Build succeeded
[mf:inf] Worker reloaded!
[mf:inf] Listening on :8787
[mf:inf] - http://192.168.3.211:8787
[mf:inf] - http://127.0.0.1:8787
[mf:err] TypeError: headers is not iterable
    at normaliseHeaders (C:\Users\tim\AppData\Local\Volta\tools\image\packages\miniflare\node_modules\miniflare\src\kv\cache.ts:28:30)
    at Cache.put (C:\Users\tim\AppData\Local\Volta\tools\image\packages\miniflare\node_modules\miniflare\src\kv\cache.ts:62:24)
    at C:\Users\tim\Documents\Choir\Choir-Platform\file\dist\main.mjs:1:565
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at EventsModule.dispatchFetch (C:\Users\tim\AppData\Local\Volta\tools\image\packages\miniflare\node_modules\miniflare\src\modules\events.ts:149:27)
    at Miniflare._Miniflare_httpRequestListener (C:\Users\tim\AppData\Local\Volta\tools\image\packages\miniflare\node_modules\miniflare\src\index.ts:408:20)
GET /file/instrument-samples/piano/A2.mp3 200 OK (8.34ms)

up to date, audited 92 packages in 677ms

8 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

> file@1.0.0 build
> rm -rf ./dist && rollup -c

[mf:err] Unable to read dist\main.mjs: Error: ENOENT: no such file or directory, open 'C:\Users\tim\Documents\Choir\Choir-Platform\file\dist\main.mjs' (defaulting to empty string)
[mf:inf] Worker reloaded!

./src/main.mjs → ./dist/main.mjs...
created ./dist/main.mjs in 249ms
[mf:inf] Build succeeded
[mf:err] GET /file/instrument-samples/piano/A2.mp3: FetchError: No fetch handler responded and unable to proxy request to upstream: no upstream specified. Have you added a fetch event listener that responds with a Response?
    at EventsModule.dispatchFetch (C:\Users\tim\AppData\Local\Volta\tools\image\packages\miniflare\node_modules\miniflare\src\modules\events.ts:167:13)
    at Miniflare.dispatchFetch (C:\Users\tim\AppData\Local\Volta\tools\image\packages\miniflare\node_modules\miniflare\src\index.ts:266:39)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at Miniflare._Miniflare_httpRequestListener (C:\Users\tim\AppData\Local\Volta\tools\image\packages\miniflare\node_modules\miniflare\src\index.ts:408:20)
GET /file/instrument-samples/piano/A2.mp3 500 Internal Server Error (67.11ms)
^C

$ miniflare

up to date, audited 92 packages in 661ms

8 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

> file@1.0.0 build
> rm -rf ./dist && rollup -c


./src/main.mjs → ./dist/main.mjs...
created ./dist/main.mjs in 249ms
[mf:inf] Build succeeded
[mf:inf] Worker reloaded!
[mf:inf] Listening on :8787
[mf:inf] - http://192.168.3.211:8787
[mf:inf] - http://127.0.0.1:8787
GET /file/instrument-samples/piano/A2.mp3 200 OK (9.51ms)
@mrbbot
Copy link
Contributor

mrbbot commented Aug 22, 2021

Hello! 👋 I think the issue here is the rm -rf ./dist in your build script. When Miniflare detects a change in your build watch path, it will trigger a rebuild but won't reload the worker. The worker is only reloaded when your script changes (Miniflare assumes this means the build has completed). However, in your case, you're removing the dist directory, so Miniflare thinks the build is done and tries to load an empty script with no fetch handler.

You should be able to fix this by removing the rm, since Rollup overwrites output files. This is definitely a bug though, Miniflare knows when the build actually finishes, so it should reload the worker then instead.

@mrbbot mrbbot closed this as completed in dd9ed26 Aug 22, 2021
@mrbbot
Copy link
Contributor

mrbbot commented Aug 27, 2021

Just released version 1.4.0 with this fix. Please let me know if you have any other issues or feedback. 😄

@evrys
Copy link

evrys commented Dec 9, 2021

Hmm, I'm still running into this issue on Windows with 1.4.1 (but not macos, where it works as expected). I run webpack and miniflare together with concurrently, the two processes look like this:

{
    "server-webpack": "webpack -w --config webpack.server.config.js",
    "server-miniflare": "miniflare --kv=STORE --watch --debug server/devdist/worker.js"
}

After any code change, all requests throw FetchError: no fetch handler responded

I don't thiink I'm removing devdist at any point, unless webpack does that by default somehow.

Ideally, I would prefer miniflare not to handle the build part and instead just watch the output, because it's faster DX to run webpack watch separately than to have miniflare reinvoke a webpack build from scratch each time (due to the startup overhead).

I think the problem might be that it reloads worker.js when webpack starts writing to it, instead of when it finishes? The log looks like this:

[server-webpack] webpack 5.56.0 compiled successfully in 95 ms
[server-miniflare] [mf:dbg] server\devdist\worker.js changed, reloading...
[server-miniflare] [mf:dbg] Reloading server\devdist\worker.js...
[server-miniflare] [mf:inf] Worker reloaded! (0B)
[server-webpack] asset worker.js 1.73 MiB [emitted] (name: worker) 1 related asset

evrys added a commit to evrys/miniflare that referenced this issue Dec 9, 2021
Fixes some cases of cloudflare#34 where miniflare reloads the worker
js file as it is being written to (e.g. by webpack), rather
than when it has finished emitting. Seems to particularly be
a problem on Windows.
@evrys
Copy link

evrys commented Dec 9, 2021

I've put in a pull request to fix this (at least for my particular scenario, hopefully also others) by using chokidar's awaitWriteFinish option to check that the file isn't actively in the process of being altered before reloading it.

@Kostanos
Copy link

Hey, the issue seems to be very old, but I'm having the same problem.
Trying to make miniflare to work with ES6 module and no luck yet.
Tried with both, webpack and esbuild.

image

Any idea?

PS. removing build instructions and running with wrangler dev works as expected.

@mrbbot
Copy link
Contributor

mrbbot commented Mar 23, 2023

Hey @Kostanos! It looks like you've got the -m flag enabled which expects a modules format (export default { fetch() { ... } }) Worker. I'm guessing you're using a service worker format (addEventListener("fetch", ...)) Worker instead. Try removing -m from your Miniflare command. 👍

@Kostanos
Copy link

Actually I'm using the "module" type, here is a small shot of my code.

// eslint-disable-next-line import/no-unresolved
import { verifyIdToken } from 'web-auth-library/google';
import { v4 as uuidv4 } from 'uuid';
import { parseToken } from './helpers';

export default {
  /**
   *
   * @param {import("@cloudflare/workers-types/experimental").Request} request
   * @param {object} env
   * @param {import("@cloudflare/workers-types/experimental").ExecutionContext} _ctx
   * @returns {Promise<Response>}
   */
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  async fetch(request, env, _ctx) {
    // Only accept a PUT request
    if (request.method !== 'PUT') {
      return new Response('{"error": "Bad request!"}');
    }
    let envCheck;
    if (!((envCheck = 'GOOGLE_CLOUD_CREDENTIALS') in env)) throw new Error(`Missing ${envCheck} environment variable`);
    if (!((envCheck = 'AUTH_KEY_SECRET') in env)) throw new Error(`Missing ${envCheck} environment variable`);
    if (!((envCheck = 'R2_BUCKET') in env)) throw new Error(`Missing ${envCheck} environment variable`);

    try {
      const idToken = parseToken(request);
    ...

BTW. I decided to give up with cloudflare server-less for the moment and will implement the traditional micro-services architecture with nodejs. I spent 3-4 days to make the following stack work together:

  • Cloudflare Worker
  • ES6
  • uuid
  • Firebase Auth
  • Cloudflare R2
  • Jest Unittests
  • GraphQL client

and I failed. I've tried both, wrangler dev and miniflare, each of them has its own issue...
There is so much workarounds and hacks need to be done to make it works.

With micro-services I can make it work in one day.

Thank you for your help anyway.

@aseure
Copy link

aseure commented May 3, 2023

Any news on this? I'm facing the same issue as @Kostanos:

And I'm also getting FetchError [ERR_NO_HANDLER]: No fetch handler defined and no upstream to proxy to specified.

@mxschumacher
Copy link

mxschumacher commented May 21, 2023

Hello - I'm struggling with the same issue when running npm run dev, which in my case is: miniflare --watch --debug --modules

I'm using wrangler 3.0.0 and am trying to make the module syntax work.

The NODE_OPTIONS=--experimental-vm-modules should only apply to API usage, e.g. not if you use miniflare as a CLI.

When I use wrangler dev --local, I run into the issue described here: cloudflare/workers-sdk#3262 - not sure whether they are related?

I would say we should reopen this thread.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants