router icon indicating copy to clipboard operation
router copied to clipboard

Start: Invalid lazy handler result and v1.121.0 migration failing

Open heystevegray opened this issue 7 months ago • 22 comments

Which project does this relate to?

Start

Describe the bug

  • The bug
  • Trying to migrate
  • Not migrating at this time
  • New project

The bug

A few days ago I couldn't start my dev server anymore with npm run dev.

npm run dev

> [email protected] dev
> vinxi dev --host

vinxi v0.5.7
Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './config' is not defined by "exports" in /Users/me/app/node_modules/@tanstack/react-start/package.json imported from /Users/me/app/app.config.timestamp_1750004498370.js
    at exportsNotFound (node:internal/modules/esm/resolve:296:10)
    at packageExportsResolve (node:internal/modules/esm/resolve:643:9)
    at packageResolve (node:internal/modules/esm/resolve:823:14)
    at moduleResolve (node:internal/modules/esm/resolve:907:18)
    at defaultResolve (node:internal/modules/esm/resolve:1037:11)
    at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:650:12)
    at #cachedDefaultResolve (node:internal/modules/esm/loader:599:25)
    at ModuleLoader.resolve (node:internal/modules/esm/loader:582:38)
    at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:241:38)
    at ModuleJob._link (node:internal/modules/esm/module_job:132:49) {
  code: 'ERR_PACKAGE_PATH_NOT_EXPORTED'
}

 ERROR  Cannot read properties of undefined (reading 'config')                                                                             12:21:38 PM

    at Object.run (node_modules/vinxi/bin/cli.mjs:79:9)
    at async runCommand (node_modules/citty/dist/index.mjs:316:16)
    at async runCommand (node_modules/citty/dist/index.mjs:307:11)
    at async runMain (node_modules/citty/dist/index.mjs:445:7) 



 ERROR  Cannot read properties of undefined (reading 'config')                                                                             12:21:38 PM

My package.json looked like this:

{
  "@tanstack/react-router": "^1.120.5",
  "@tanstack/react-start": "^1.120.5",
  "vinxi": "^0.5.6",
}

Trying to migrate

I then found this migration guide for v1.121.0 in Start BETA - Tracking: https://github.com/TanStack/router/discussions/2863#discussioncomment-13104960. In a new branch I followed these steps. Then I ran npm run build and npm run start and I see this error:

TypeError: Invalid lazy handler result. It should be a function: at file:///Users/me/app/.output/server/index.mjs:1473:17

My localhost shows this in the browser:

{
  "error": true,
  "url": "http://[::]:3000/",
  "statusCode": 500,
  "statusMessage": "Server Error",
  "message": "Server Error"
}

And my terminal shows this:

 npm run start

> [email protected] start
> node .output/server/index.mjs

Listening on http://[::]:3000
[request error] [unhandled] [GET] http://[::]:3000/
 TypeError: Invalid lazy handler result. It should be a function:
    at file:///Users/me/app/.output/server/index.mjs:1473:17
    at async Object.handler (file:///Users/me/app/.output/server/index.mjs:1557:19)
    at async Server.toNodeHandle (file:///Users/me/app/.output/server/index.mjs:1828:7) {
  cause: TypeError: Invalid lazy handler result. It should be a function:
      at file:///Users/me/app/.output/server/index.mjs:1473:17
      at async Object.handler (file:///Users/me/app/.output/server/index.mjs:1557:19)
      at async Server.toNodeHandle (file:///Users/me/app/.output/server/index.mjs:1828:7),
  statusCode: 500,
  fatal: false,
  unhandled: true,
  statusMessage: undefined,
  data: undefined
}
[unhandledRejection] Error: Invalid environment variables
    at onValidationError (file:///Users/me/app/.output/server/node_modules/@t3-oss/env-core/dist/src-Cq4nGjdj.js:53:9)
    at createEnv (file:///Users/me/app/.output/server/node_modules/@t3-oss/env-core/dist/src-Cq4nGjdj.js:58:28)
    at file:///Users/me/app/.output/server/chunks/_/ssr.mjs:2136:15
    at file:///Users/me/app/.output/server/chunks/_/ssr.mjs:5818:3
    at ModuleJob.run (node:internal/modules/esm/module_job:268:25)
    at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:543:26)
    at async Object.handler (file:///Users/me/app/.output/server/index.mjs:1557:19)
    at async Server.toNodeHandle (file:///Users/me/app/.output/server/index.mjs:1828:7)
[request error] [unhandled] [GET] http://[::]:3000/favicon.ico
 TypeError: Invalid lazy handler result. It should be a function:
    at file:///Users/me/app/.output/server/index.mjs:1473:17
    at async Object.handler (file:///Users/me/app/.output/server/index.mjs:1557:19)
    at async Server.toNodeHandle (file:///Users/me/app/.output/server/index.mjs:1828:7) {
  cause: TypeError: Invalid lazy handler result. It should be a function:
      at file:///Users/me/app/.output/server/index.mjs:1473:17
      at async Object.handler (file:///Users/me/app/.output/server/index.mjs:1557:19)
      at async Server.toNodeHandle (file:///Users/me/app/.output/server/index.mjs:1828:7),
  statusCode: 500,
  fatal: false,
  unhandled: true,
  statusMessage: undefined,
  data: undefined
}

Here is my vite.config.ts file. I'm trying to use https://env.t3.gg/docs/core for environment variable safety, thats why you see these lines:

import 'dotenv/config'
import './src/env'

My vite.config.ts file:

import { tanstackStart } from '@tanstack/react-start/plugin/vite'
import { defineConfig } from 'vite'
import topLevelAwait from 'vite-plugin-top-level-await'
import tsConfigPaths from 'vite-tsconfig-paths'
import 'dotenv/config'
import './src/env'

export default defineConfig({
  server: {
    port: 3000,
  },
  plugins: [
    tsConfigPaths({
      projects: ['./tsconfig.json'],
    }),
    tanstackStart({
      target: 'node-server',
    }),
    topLevelAwait(),
  ],
})

Not migrating at this time

I also attempted the "pinning" suggestion at the bottom of this link: https://github.com/TanStack/router/discussions/2863#discussioncomment-13104960

npx create-start-app@latest pin-versions
10 packages updated.

Remove your node_modules directory and package lock file and re-install.

This updated the following packages in my package.json file

{
  "@tanstack/react-router": "1.120.5",
  "@tanstack/react-router-devtools": "1.120.5",
  "@tanstack/react-start": "1.120.5",
  "@tanstack/react-start-client": "1.120.5",
  "@tanstack/react-start-config": "1.120.5",
  "@tanstack/react-start-plugin": "1.120.5",
  "@tanstack/react-start-server": "1.120.5",
  "@tanstack/router-generator": "1.120.5",
  "@tanstack/router-plugin": "1.120.5",
  "@tanstack/start-server-core": "1.120.5",
}

I removed node_modules and package-lock.json, then ran npm i again. But then I see this error:

No matching version found for @tanstack/[email protected]

npm i

npm error code ETARGET
npm error notarget No matching version found for @tanstack/[email protected].
npm error notarget In most cases you or one of your dependencies are requesting
npm error notarget a package version that doesn't exist.
npm error A complete log of this run can be found in: /Users/me/.npm/_logs/2025-06-15T17_20_33_118Z-debug-0.log

New project

I followed the steps here to build a project from scratch and I can successfully run npm run build and npm run start with these scripts:

"scripts": {
  "dev": "vite dev",
  "build": "vite build",
  "start": "node .output/server/index.mjs"
}

My working example repo is here: https://github.com/heystevegray/tanstack-start-beta-bug

I'm not sure why a new project seems to work but mine cannot start.

Your Example Website or App

https://github.com/heystevegray/tanstack-start-beta-bug

Steps to Reproduce the Bug or Issue

  1. Follow this migration guide: https://github.com/TanStack/router/discussions/2863#discussioncomment-13104960 with an older version of tanstack start
    {
      "@tanstack/react-router": "^1.120.5",
      "@tanstack/react-start": "^1.120.5",
      "vinxi": "^0.5.6",
    }
    
  2. Run npm run build
  3. Run npm run start
  4. I see this in the terminal:

    TypeError: Invalid lazy handler result. It should be a function: at file:///Users/me/app/.output/server/index.mjs:1473:17

Expected behavior

I expect after following the migration guide here https://github.com/TanStack/router/discussions/2863#discussioncomment-13104960 that I can build and start my project with:

"start": "node .output/server/index.mjs"

Screenshots or Videos

No response

Platform

  • OS: macOS
  • Browser: Arc
  • Version: Arc 1.99.0 (64212)

Additional context

No response

heystevegray avatar Jun 15 '25 18:06 heystevegray

can you please share a failing reproducer?

schiller-manuel avatar Jun 15 '25 18:06 schiller-manuel

@schiller-manuel Here is a failing reproducer of he "pin-versions" error from the bottom of this guide https://github.com/TanStack/router/discussions/2863#discussioncomment-13104960. The example is on a branch called pinning: https://github.com/heystevegray/tanstack-start-beta-bug/tree/pinning

Here are the commits I made following the migration guide: https://github.com/heystevegray/tanstack-start-beta-bug/compare/main...pinning

Here is an old tanstack start starting point: https://github.com/heystevegray/tanstack-start-beta-bug/commit/3c517542a3ff33fc48bc9157c2c6a89b30b4fa58

  1. Pull the repo and cd to the project

    git clone [email protected]:heystevegray/tanstack-start-beta-bug.git
    cd tanstack-start-beta-bug
    
  2. Checkout the pinning branch

    git checkout pinning
    
  3. Run npm i and it will fail

    npm i
    npm error code ETARGET
    npm error notarget No matching version found for @tanstack/[email protected].
    npm error notarget In most cases you or one of your dependencies are requesting
    npm error notarget a package version that doesn't exist.
    npm error A complete log of this run can be found in: /Users/me/.npm/_logs/2025-06-15T19_57_19_616Z-debug-0.log
    

I'm still trying to make a failing reproducer for the TypeError: Invalid lazy handler result. It should be a function: issue.

heystevegray avatar Jun 15 '25 20:06 heystevegray

that version does indeed not exist. see https://www.npmjs.com/package/@tanstack/react-router-devtools?activeTab=versions

Image

schiller-manuel avatar Jun 15 '25 20:06 schiller-manuel

please check if https://github.com/TanStack/router/issues/4432 is showing the same issue as you have with the "invalid lazy handler"

schiller-manuel avatar Jun 15 '25 20:06 schiller-manuel

that version does indeed not exist. see https://www.npmjs.com/package/@tanstack/react-router-devtools?activeTab=versions

Image

I see, it seems the helper from the bottom of this guide https://github.com/TanStack/router/discussions/2863#discussioncomment-13104960 (npx create-start-app@latest pin-versions) is behaving in different ways.

  1. In my demo repository https://github.com/TanStack/router/issues/4431#issuecomment-2974669641 it added @tanstack/[email protected] to the package.json which doesn't exist.

  2. In my project repo I tried the same helper and it added @tanstack/[email protected] to the package.json which doesn't exist. https://www.npmjs.com/package/@tanstack/react-start-plugin?activeTab=versions

    Image
    npm i
    npm error code ETARGET
    npm error notarget No matching version found for @tanstack/[email protected].
    npm error notarget In most cases you or one of your dependencies are requesting
    npm error notarget a package version that doesn't exist.
    npm error A complete log of this run can be found in: /Users/me/.npm/_logs/2025-06-15T20_33_39_932Z-debug
    

If I manually install this version I can get my dev server running

npm i @tanstack/[email protected]

But when I open localhost in the browser I see an issue with the loader data and the app never loads

Error in renderToPipeableStream: TypeError: Cannot destructure property 'defaultOpen' of 'Route.useLoaderData(...)' as it is undefined.

Error in renderToPipeableStream: TypeError: Cannot destructure property 'defaultOpen' of 'Route.useLoaderData(...)' as it is undefined.
    at RootDocument (/Users/me/app/app/routes/__root.tsx:88:11)
    at renderWithHooks (/Users/me/app/node_modules/react-dom/cjs/react-dom-server.node.development.js:5724:16)
    at renderIndeterminateComponent (/Users/me/app/node_modules/react-dom/cjs/react-dom-server.node.development.js:5798:15)
    at renderElement (/Users/me/app/node_modules/react-dom/cjs/react-dom-server.node.development.js:6023:7)
    at renderNodeDestructiveImpl (/Users/me/app/node_modules/react-dom/cjs/react-dom-server.node.development.js:6181:11)
    at renderNodeDestructive (/Users/me/app/node_modules/react-dom/cjs/react-dom-server.node.development.js:6153:14)
    at renderIndeterminateComponent (/Users/me/app/node_modules/react-dom/cjs/react-dom-server.node.development.js:5852:7)
    at renderElement (/Users/me/app/node_modules/react-dom/cjs/react-dom-server.node.development.js:6023:7)
    at renderNodeDestructiveImpl (/Users/me/app/node_modules/react-dom/cjs/react-dom-server.node.development.js:6181:11)
    at renderNodeDestructive (/Users/me/app/node_modules/react-dom/cjs/react-dom-server.node.development.js:6153:14) undefined

heystevegray avatar Jun 15 '25 20:06 heystevegray

please check if #4432 is showing the same issue as you have with the "invalid lazy handler"

From #4432

Note: this works ok in dev. It is only triggered by building and running a server (tested with node-server and aws-lambda targets).

Yes this appears to be the same issue I'm seeing. I can run ok in dev, but I cannot build and start (Run node .output/server/index.mjs). I was targeting node-server.

heystevegray avatar Jun 15 '25 21:06 heystevegray

so you also have tsr.srcDirectory set to . ?

schiller-manuel avatar Jun 15 '25 21:06 schiller-manuel

Oh sorry, no I do not have tsr.srcDirectory set to . in vite.config.ts. I just set the target: 'node-server'

// vite.config.ts
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
import { defineConfig } from 'vite'
import topLevelAwait from 'vite-plugin-top-level-await'
import tsConfigPaths from 'vite-tsconfig-paths'
import 'dotenv/config'
import './src/env'

export default defineConfig({
  server: {
    port: 3000,
  },
  plugins: [
    tsConfigPaths({
      projects: ['./tsconfig.json'],
    }),
    tanstackStart({
      target: 'node-server', // No tsr.srcDirectory
    }),
    topLevelAwait(),
  ],
})

I tried to set the value and and build and this happened:

tanstackStart({
    target: 'node-server',
    tsr: {
        srcDirectory: '.',
    },
})

Failed to build

Error: ENOENT: no such file or directory, scandir '/Users/me/app/routes'

and this

[vite]: Rollup failed to resolve import "/Users/me/app/router" from "/~start/default-client-entry.tsx".

npm run build

> [email protected] build
> vite build && tsc --noEmit

vite v6.3.5 building for production...
Error: ENOENT: no such file or directory, scandir '/Users/me/app/routes'
    at file:///Users/me/app/node_modules/@tanstack/router-generator/dist/esm/generator.js:142:19
    at async generate (file:///Users/me/app/node_modules/@tanstack/router-plugin/dist/esm/core/router-generator-plugin.js:34:7)
    at async Object.buildStart (file:///Users/me/app/node_modules/@tanstack/router-plugin/dist/esm/core/router-generator-plugin.js:61:9)
    at async Promise.all (index 2)
    at async PluginDriver.hookParallel (file:///Users/me/app/node_modules/rollup/dist/es/shared/node-entry.js:22166:9)
    at async file:///Users/me/app/node_modules/rollup/dist/es/shared/node-entry.js:23130:13
    at async catchUnfinishedHookActions (file:///Users/me/app/node_modules/rollup/dist/es/shared/node-entry.js:22608:16)
    at async rollupInternal (file:///Users/me/app/node_modules/rollup/dist/es/shared/node-entry.js:23127:5)
    at async buildEnvironment (file:///Users/me/app/node_modules/vite/dist/node/chunks/dep-DBxKXgDP.js:46206:14)
    at async Object.buildApp (file:///Users/me/app/node_modules/@tanstack/start-plugin-core/dist/esm/nitro-plugin/plugin.js:45:15)
✓ 2 modules transformed.
✗ Build failed in 16ms
error during build:
[vite]: Rollup failed to resolve import "/Users/me/app/router" from "/~start/default-client-entry.tsx".
This is most likely unintended because it can break your application at runtime.
If you do want to externalize this module explicitly add it to
`build.rollupOptions.external`
    at viteLog (file:///Users/me/app/node_modules/vite/dist/node/chunks/dep-DBxKXgDP.js:46345:15)
    at file:///Users/me/app/node_modules/vite/dist/node/chunks/dep-DBxKXgDP.js:46403:18
    at onwarn (file:///Users/me/app/node_modules/@vitejs/plugin-react/dist/index.mjs:104:9)
    at file:///Users/me/app/node_modules/vite/dist/node/chunks/dep-DBxKXgDP.js:46401:7
    at onRollupLog (file:///Users/me/app/node_modules/vite/dist/node/chunks/dep-DBxKXgDP.js:46393:5)
    at onLog (file:///Users/me/app/node_modules/vite/dist/node/chunks/dep-DBxKXgDP.js:46043:7)
    at file:///Users/me/app/node_modules/rollup/dist/es/shared/node-entry.js:20772:32
    at Object.logger [as onLog] (file:///Users/me/app/node_modules/rollup/dist/es/shared/node-entry.js:22651:9)
    at ModuleLoader.handleInvalidResolvedId (file:///Users/me/app/node_modules/rollup/dist/es/shared/node-entry.js:21398:26)
    at file:///Users/me/app/node_modules/rollup/dist/es/shared/node-entry.js:21356:26

This migration guide https://github.com/TanStack/router/discussions/2863#discussioncomment-13104960 said to delete the client entry files if you didn't customize them. I did not customize them and deleted them.

Delete src/client.tsx and src/ssr.tsx If you did NOT customize your src/client.tsx and src/ssr.tsx files, then you can delete them. - Source

heystevegray avatar Jun 15 '25 21:06 heystevegray

After I made sure to remove all Vinxi-related code from my workspace, it started working. A small change from the renamed file ssr.tsx to server.tsx allowed the API routes to function well.

You have modified your client.tsx file; make sure to remove all Vinxi references.

Remove all /// <reference types="vinxi/types/client" />

Change the import from import { getWebRequest } from "vinxi/http"; to import { getWebRequest } from "@tanstack/react-start/server"; in your server.ts file if you use it.

You need to remove all imports under the Vinxi namespace: import ... from "vinxi/...." and fix the API routes.

- import { createAPIFileRoute } from "@tanstack/react-start/api";
+ import { createServerFileRoute } from "@tanstack/react-start/server";

https://github.com/TanStack/router/discussions/2863#discussioncomment-11392000

MathieuDoyon avatar Jun 16 '25 15:06 MathieuDoyon

@MathieuDoyon Here are some updates but I'm still seeing this error:

TypeError: Invalid lazy handler result. It should be a function: at file:///Users/me/app/.output/server/index.mjs:1473:17

  1. I've uninstalled vinxi and didn't find any other instances of it.

  2. I've deleted client.tsx as a part of this migration guide https://github.com/TanStack/router/discussions/2863#discussioncomment-13104960.

  3. My getWebRequest is coming from here:

    import { getWebRequest } from '@tanstack/react-start/server'
    
  4. I've updated all the api routes to use ServerRoutes:

    import { createServerFileRoute } from '@tanstack/react-start/server'
    
  5. /src/sever.tsx seemed optional if you use it, but as a test I tried to add it and still no luck

    // src/server.tsx
    import { createStartHandler, defaultStreamHandler } from '@tanstack/react-start/server'
    
    import { createRouter } from './router'
    
    export default createStartHandler({
      createRouter,
    })(defaultStreamHandler)
    

heystevegray avatar Jun 16 '25 18:06 heystevegray

Mmm there seems to be an issue with today's released versions 1.121.17 and 1.121.18, i noticed node_module packages depending on these versions don't have a dist folder causing not found errors here and there. My problems started to happen after deleted the lock file, new generated one depends on .17 or 18 even though i install packages with -E 1.121.16

Crsk avatar Jun 16 '25 21:06 Crsk

@heystevegray this workaround might help with your "Invalid lazy handler" error https://github.com/TanStack/router/issues/4432#issuecomment-2979675209

djgrant avatar Jun 17 '25 09:06 djgrant

@djgrant Thank you for the suggestion, but it did not work for me.

  1. This morning I upgraded dependencies

     "@tanstack/react-router": "^1.121.21",
     "@tanstack/react-start": "^1.121.21",
    
  2. I added nitro.config.ts to my root directory. I ran npm run build and npm run start and I still see

    TypeError: Invalid lazy handler result. It should be a function: at file:///Users/me/app/.output/server/index.mjs:1473:17

    // nitro.config.ts
    export default defineNitroConfig({
        // prevent nitro picking up tanstack routes
        // https://github.com/TanStack/router/issues/4432
        apiDir: "non-existent-dir",
        routesDir: "non-existent-dir",
    });
    
  3. Also tried to pin the versions again this morning with npx create-start-app@latest pin-versions and this time it tried to install @tanstack/[email protected] which doesn't exist.

     ❯ npx create-start-app@latest pin-versions
     10 packages updated.
    
     Remove your node_modules directory and package lock file and re-install.
     ❯ npm i
     npm error code ETARGET
     npm error notarget No matching version found for @tanstack/[email protected].
     npm error notarget In most cases you or one of your dependencies are requesting
     npm error notarget a package version that doesn't exist.
     npm error A complete log of this run can be found in: /Users/me/.npm/_logs/2025-06-17T14_44_22_310Z-debug-0.log
    

heystevegray avatar Jun 17 '25 14:06 heystevegray

Not sure if this is helpful to your issue, but I'll share what I learned from my own debugging.

That error occurred for me because the nitro build was picking up tanstack routes and including them in its router (see https://nitro.build/guide/routing#filesystem-routing).

If you look in ./output/index.mjs, if everything is building correctly, you should see something like this:

const _lazy_vr5YKA = () => import('./chunks/_/ssr.mjs');

const handlers = [
  { route: '/**', handler: _lazy_vr5YKA, lazy: true, middleware: false, method: undefined }
];

I was seeing an array of all my tanstack routes, which are not nitro/h3 route handlers, hence the "Invalid lazy handler result" error.

The only handler here should be the ssr handler (in which the tanstack routing is handled).

djgrant avatar Jun 17 '25 15:06 djgrant

@djgrant Here is my ./output/index.mjs. It's the same with and without the nitro.config.ts changes. I see an extra line that is different from yours:

{ route: '', handler: _Pmmk9P, lazy: false, middleware: true, method: undefined },

// ./output/index.mjs
const _lazy_vr5YKA = () => import('./chunks/_/ssr.mjs');

const handlers = [
  { route: '', handler: _Pmmk9P, lazy: false, middleware: true, method: undefined },
  { route: '/**', handler: _lazy_vr5YKA, lazy: true, middleware: false, method: undefined }
];

heystevegray avatar Jun 17 '25 15:06 heystevegray

That looks good.

Do you have the following in ./output/chunks/_/ssr.mjs?

const serverEntry$1 = createStartHandler({
  createRouter,
})(defaultStreamHandler);

const serverEntry = defineEventHandler(function (event) {
  const request = toWebRequest(event);
  return serverEntry$1({ request });
});

export {
  ...
  serverEntry as default,
  ...
}

djgrant avatar Jun 17 '25 16:06 djgrant

No my ./output/chunks/_/ssr.mjs looks different. There is a let ..., serverEntry, ... at the top of the file and then this:

// ./output/chunks/_/ssr.mjs
const serverEntry$1 = createStartHandler({
  createRouter: createRouter$1, // createRouter$1 is different
})(defaultStreamHandler)

serverEntry = defineEventHandler$1((event) => { // no const is different
  const request = toWebRequest(event)
  return serverEntry$1({ request })
})

export {
  ...
  serverEntry as default,
  ...
}

My createRouter$1 looks like this

// ./output/chunks/_/ssr.mjs
function createRouter$1() {
  const router = createRouter({
    routeTree,
    scrollRestoration: true,
  })
  return router
}

heystevegray avatar Jun 17 '25 21:06 heystevegray

That looks fine. I think you're using the top-level await vite plugin which will put everything in an IIFE and declare serverEntry up front for the export.

That might be a thread worth pulling on. Is serverEntry reassigned anywhere?

It may also be worth putting some debug logs in the compiled output and see what's going on.

I'd start with:

const _lazy_vr5YKA = () => import("./chunks/_/ssr.mjs");

let serverEntry;

// check is handler function on initialisation
_lazy_vr5YKA().then((mod) => {
  serverEntry = mod.default;
  console.log(mod.default);
});

// check again if is still a handler function after 10 seconds
setTimeout(() => {
  console.log(serverEntry);
}, 10 * 1000);

You should get:

Listening on http://[::]:3000
[Function (anonymous)] { __is_handler__: true }
[Function (anonymous)] { __is_handler__: true }

djgrant avatar Jun 17 '25 22:06 djgrant

In my .output/server/chunks/_/ssr.mjs file serverEntry is only assigned once:

// .output/server/chunks/_/ssr.mjs
serverEntry = defineEventHandler$1((event) => {
  const request = toWebRequest(event)
  return serverEntry$1({
    request,
  })
})

I am using the topLevelAwait() plugin, here is my vite.config.ts:

// vite.config.ts
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
import { defineConfig } from 'vite'
import topLevelAwait from 'vite-plugin-top-level-await'
import tsConfigPaths from 'vite-tsconfig-paths'

export default defineConfig({
  server: {
    port: 3000,
  },
  plugins: [
    tsConfigPaths({
      projects: ['./tsconfig.json'],
    }),
    tanstackStart({
      target: 'node-server',
    }),
    topLevelAwait(),
  ],
})

For the debug logs, I don't see that output it's undefined. I added this snippet to the bottom of my .output/server/index.mjs file:

// .output/server/index.mjs
let serverEntry

// check is handler function on initialisation
_lazy_vr5YKA().then((mod) => {
  serverEntry = mod.default
  console.log(mod.default)
})

// check again if is still a handler function after 10 seconds
setTimeout(() => {
  console.log(serverEntry)
}, 10 * 1000)

Here's the output:

Listening on http://[::]:3000
undefined
undefined

heystevegray avatar Jun 18 '25 01:06 heystevegray

serverEntry being undefined will be what's causing that error. If you can figure out what's causing it to be undefined you should be a step closer to creating a reproducible.

My gut feeling is that it's something to do with the vite top level await plugin. Does it work without it? Does changing the order make any difference? Maybe put that plugin first.

djgrant avatar Jun 18 '25 16:06 djgrant

I cloned your repo and successfully migrated the pinning branch, doing a PR now

Image

EDIT: haven's read the full thread so let me know if i'm missing something important.

list of changes:

  • removed some @tanstack/[x] dependencies
    • start-server-core
    • router-generator
    • react-start-server
    • react-start-plugin
    • react-start-config
    • react-start-client
  • updated remaining @tanstack/[x] dependencies to 1.121.21
    • react-router
    • react-router-devtools
    • react-start
    • router-plugin
  • renamed app.config.ts to vite.config.ts
  • renamed app directory to src
  • removed client.tsx and ssr.tsx
  • updated vite.config.ts to match new structure
    • import defineConfig from vite instead of @tanstack/react-start/config
    • add server.port
    • remove vite object
    • add tanstackStart() plugin
  • updated package.json vinxi commands

Crsk avatar Jun 18 '25 16:06 Crsk

@Crsk thank you, let me take a look.

All, I removed the topLevelAwait() plugin in my vite.config.ts file, replaced all top level await code and I can build and start the server now.

vite.config.ts Image

heystevegray avatar Jun 18 '25 20:06 heystevegray

@heystevegray since now we have to defineConfig from vite, how does it work with deploying to CF Workers? I am having issues with "@tanstack/react-start": "^1.121.29".

And do we still need app.config.ts ?

joelfickson avatar Jun 20 '25 16:06 joelfickson

@JoelFickson This is how i did it:

vite.config.ts

import { tanstackStart } from '@tanstack/react-start/plugin/vite'
import { defineConfig } from 'vite'
import tsConfigPaths from 'vite-tsconfig-paths'

export default defineConfig({
  server: {
    port: 3000
  },
  plugins: [
    tsConfigPaths({
      projects: ['./tsconfig.json']
    }),
    tanstackStart({
      target: 'cloudflare_module'
    })
  ]
})

wrangler.toml

"$schema" = "node_modules/wrangler/config-schema.json"
name = "this_should_match_your_worker"
main = "./.output/server/index.mjs"
compatibility_date = "2025-04-14"
compatibility_flags = [ "nodejs_compat" ]

[observability]
enabled = true

[assets]
directory = "./.output/public/"

package.json

{
  "scripts": {
    "dev": "vite",
    "build": "vite build && tsc --noEmit",
    "start": "node .output/server/index.mjs",
    "deploy": "npm run build && wrangler deploy --minify ./.output/server/index.mjs"
  },
  "devDependencies": {
    "wrangler": "^4.20.0"
  }
}

Crsk avatar Jun 20 '25 16:06 Crsk

@heystevegray since now we have to defineConfig from vite, how does it work with deploying to CF Workers? I am having issues with "@tanstack/react-start": "^1.121.29".

And do we still need app.config.ts ?

@Crsk thanks for sharing.

@JoelFickson app.config.ts was replaced by vite.config.ts as part of this migration guide https://github.com/TanStack/router/discussions/2863#discussioncomment-13104960

If you mean Cloudflare Workers I'm not familiar with deploying that. I did find this section in the docs: https://tanstack.com/start/latest/docs/framework/react/hosting#cloudflare-pages

And you can change the target in the tanstack start plugin:

// vite.config.ts
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
import { defineConfig } from 'vite'

export default defineConfig({
  plugins: [
    tanstackStart({
      target: 'cloudflare-worker', // Modify this
    }),
  ],
})
Image

heystevegray avatar Jun 20 '25 17:06 heystevegray

@JoelFickson This is how i did it:

vite.config.ts

import { tanstackStart } from '@tanstack/react-start/plugin/vite' import { defineConfig } from 'vite' import tsConfigPaths from 'vite-tsconfig-paths'

export default defineConfig({ server: { port: 3000 }, plugins: [ tsConfigPaths({ projects: ['./tsconfig.json'] }), tanstackStart({ target: 'cloudflare_module' }) ] }) wrangler.toml

"$schema" = "node_modules/wrangler/config-schema.json" name = "this_should_match_your_worker" main = "./.output/server/index.mjs" compatibility_date = "2025-04-14" compatibility_flags = [ "nodejs_compat" ]

[observability] enabled = true

[assets] directory = "./.output/public/" package.json

{ "scripts": { "dev": "vite", "build": "vite build && tsc --noEmit", "start": "node .output/server/index.mjs", "deploy": "npm run build && wrangler deploy --minify ./.output/server/index.mjs" }, "devDependencies": { "wrangler": "^4.20.0" } }

Thanks. This helped.

joelfickson avatar Jun 20 '25 18:06 joelfickson

@heystevegray thanks. Worked for me.

joelfickson avatar Jun 20 '25 18:06 joelfickson

Can this issue be closed?

brenelz avatar Jul 10 '25 21:07 brenelz

Sure it's done. @heystevegray

Crsk avatar Jul 19 '25 22:07 Crsk