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

dev server Cannot read property 'version' of undefined #7081

Closed
1 task done
divyeshsachan opened this issue Aug 5, 2023 · 2 comments
Closed
1 task done

dev server Cannot read property 'version' of undefined #7081

divyeshsachan opened this issue Aug 5, 2023 · 2 comments
Labels
bug:unverified feat:dx Issues related to the developer experience package:dev

Comments

@divyeshsachan
Copy link

What version of Remix are you using?

1.19.2

Are all your remix dependencies & dev-dependencies using the same version?

  • Yes

Steps to Reproduce

Sometimes, LiveReload crash the dev v2 server after saving files.

To reproduce, create a new example app from remix

  1. Run the dev server
  2. add import of another file and call its method in code and save. (Dev server will livereload ok)
  3. remove the same import file and its method from code and save. (Dev server will livereload ok)
  4. do undo remove of import and its calling method and save. (Dev server crashes)

In real project, it happens frequently as when we add or remove imports and save it.

Crash at line 66 at broadcastDevReady in server.ts
server.ts FILE

import * as fs from "node:fs";

import { createRequestHandler } from "@remix-run/express";
import { broadcastDevReady, installGlobals } from "@remix-run/node";
import chokidar from "chokidar";
import compression from "compression";
import express from "express";
import morgan from "morgan";
import sourceMapSupport from "source-map-support";

sourceMapSupport.install();
installGlobals();

const BUILD_PATH = "./build/index.js";
/**
 * @type { import('@remix-run/node').ServerBuild | Promise<import('@remix-run/node').ServerBuild> }
 */
let build = await import(BUILD_PATH);

const app = express();

app.use(compression());

// http://expressjs.com/en/advanced/best-practice-security.html#at-a-minimum-disable-x-powered-by-header
app.disable("x-powered-by");

// Remix fingerprints its assets so we can cache forever.
app.use(
  "/build",
  express.static("public/build", { immutable: true, maxAge: "1y" })
);

// Everything else (like favicon.ico) is cached for an hour. You may want to be
// more aggressive with this caching.
app.use(express.static("public", { maxAge: "1h" }));

app.use(morgan("tiny"));

app.all(
  "*",
  process.env.NODE_ENV === "development"
    ? createDevRequestHandler()
    : createRequestHandler({
        build,
        mode: process.env.NODE_ENV,
      })
);

const port = process.env.PORT || 3000;
app.listen(port, async () => {
  console.log(`Express server listening on port ${port}`);

  if (process.env.NODE_ENV === "development") {
    broadcastDevReady(build);
  }
});

function createDevRequestHandler() {
  const watcher = chokidar.watch(BUILD_PATH, { ignoreInitial: true });

  watcher.on("all", async () => {
    // 1. purge require cache && load updated server build
    const stat = fs.statSync(BUILD_PATH);
    build = import(BUILD_PATH + "?t=" + stat.mtimeMs);
    // 2. tell dev server that this app server is now ready
    broadcastDevReady(await build);  //CRASH HERE
  });

  return async (req, res, next) => {
    try {
      //
      return createRequestHandler({
        build: await build,
        mode: "development",
      })(req, res, next);
    } catch (error) {
      next(error);
    }
  };
}

BROWSER CRASH LOGS

TypeError: Cannot convert undefined or null to object
    at Function.values (<anonymous>)
    at groupRoutesByParentId (/home/user/testremix/remix/node_modules/@remix-run/server-runtime/dist/routes.js:23:10)
    at Object.createRoutes (/home/user/testremix/remix/node_modules/@remix-run/server-runtime/dist/routes.js:35:67)
    at Object.createRequestHandler (/home/user/testremix/remix/node_modules/@remix-run/server-runtime/dist/server.js:27:25)
    at createRequestHandler (/home/user/testremix/remix/node_modules/@remix-run/express/dist/server.js:34:28)
    at file:///home/divyeshsachan/testremix/remix/server.js:72:14

Upon debugging found that, in /home/user/testremix/remix/node_modules/@remix-run/server-runtime/dist/dev.js
build.asset is null and that leads to crash upon reading version from it.

async function broadcastDevReady(build, origin) {
  origin ?? (origin = process.env.REMIX_DEV_HTTP_ORIGIN);
  if (!origin) throw Error("Dev server origin not set");
  let url = new URL(origin);
  url.pathname = "ping";
  let response = await fetch(url.href, {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      buildHash: build.assets.version
    })
  }).catch(error => {
    console.error(`Could not reach Remix dev server at ${url}`);
    throw error;
  });
  if (!response.ok) {
    console.error(`Could not reach Remix dev server at ${url} (${response.status})`);
    throw Error(await response.text());
  }
}

Expected Behavior

It should not crash

Actual Behavior

Console CARSH logs

 info  rebuilding... (~ app/routes/_index.tsx)
 info  rebuilt (129ms)
(node:135194) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'version' of undefined
    at broadcastDevReady (/home/user/testremix/remix/node_modules/@remix-run/server-runtime/dist/dev.js:26:31)
    at FSWatcher.<anonymous> (file:///home/user/testremix/remix/server.js:66:5)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:135194) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:135194) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
POST /?index=&_data=routes%2F_index 500 871 - 2.657 ms
@divyeshsachan
Copy link
Author

It seems the issue is similar to the issue already reported in #6919

Please check if closing #6919 will fix it !

@brophdawg11 brophdawg11 added package:dev feat:dx Issues related to the developer experience labels Aug 7, 2023
@pcattori
Copy link
Contributor

pcattori commented Aug 7, 2023

Duplicate of #6919

@pcattori pcattori marked this as a duplicate of #6919 Aug 7, 2023
@pcattori pcattori closed this as completed Aug 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug:unverified feat:dx Issues related to the developer experience package:dev
Projects
None yet
Development

No branches or pull requests

3 participants