Skip to content

[Bug?]: syntax errors in ./app.tsx causes uncaught 500 error #1648

Open

Description

@bigmistqke

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

Current behavior 😯

When editing app.tsx the website will 500 when the app i in an incorrect state. The dev-overlay is visible for a fraction of a second and then the default browser display is shown. The app is then not being able to get recovered with hmr.

Screen.Recording.2024-10-06.at.04.45.41.mov

When editing a file that app.tsx imports (and renders), the error does not occur:

Screen.Recording.2024-10-06.at.04.47.21.mov

It was slightly different behavior in the context of where I found out about the bug. I am making a sveltelab thingy for the hackathon, a repl powered by stackblitz' webcontainers. There some imports did cause similar 500s.

solidlab2.mp4

routes that are currently rendered can also be edited without 500, it's only app.tsx

basic.mp4

Expected behavior 🤔

To be able to write invalid code without the app getting in to an unrecoverable 500-error.

Steps to reproduce 🕹

Steps:

  1. clone the bare solid start example
  2. pnpm install && pnpm dev
  3. edit src/app.tsx so it is invalid javascript and save
  4. see that page 500s without dev-overlay
  5. edit src/app.tsx so it is valid again
  6. see that it does not reload

Context 🔦

No response

Your environment 🌎

No response

Activity

  1. ryansolid commented on Oct 31, 2024

    @ryansolid
    Member

    Hmm.. trying to think about who to get to look at this one. HMR behavior here could be related to Vinxi (@nksaraf) or it could be related to solid refresh or the overlay (@lxsmnsyc). Maybe either of them would have a better idea of how this should be working.

  2. atilafassina commented on Feb 12, 2025

    @atilafassina
    Member

    @lxsmnsyc can you please let us know if this is a Solid-Refresh issue? 👀

  3. birkskyum commented on Jul 27, 2026

    @birkskyum
    Member

    Revisited on v2. The setup in the original report is fixed; the bug is still reproducible with Nitro, and the real fix belongs upstream.

    Fixed for the no-Nitro case. This was filed against v1, on Vinxi. The dev server now serves an error page that mounts Vite's ErrorOverlay (added in #1942, the PR that removed Vinxi), and Vite's client reloads it on the next update (if (isFirstUpdate && hasErrorOverlay()) location.reload()). Verified on unmodified main with a plugins: [solidStart()] app: break app.tsx, fix it, the page comes back on its own in ~0.5s.

    Still broken with nitro(). Nitro implements dispatchFetch, so devServer() steps aside and Nitro renders SSR errors itself using Youch. That page has no /@vite/client and no vite-error-overlay, so it has no HMR connection and qualifies for neither of Vite's recovery paths. Fix the file and nothing reaches the browser. Same app, only difference is nitro() in the plugin list.

    Fix belongs in Nitro. I tried patching the src/runtime/internal/error/dev.ts locally to append a Vite client + reload script to the HTML error page, removed all SolidStart-side changes, and the Nitro setup recovered in ~0.5s. So an upstream fix is sufficient on its own.

    Leaving this open to track until that lands.

  4. removed theissue type on Jul 27, 2026
  5. birkskyum commented on Jul 27, 2026

    @birkskyum
    Member

    The exact patch i applied to nitro is insrc/runtime/internal/error/dev.ts:83-96, where

    -    body: await youch.toHTML(error, {
    -      request: {
    -        url: url.href,
    -        method: event.req.method,
    -        headers: Object.fromEntries(event.req.headers.entries()),
    -      },
    -    }),
    +    body:
    +      (await youch.toHTML(error, {
    +        request: {
    +          url: url.href,
    +          method: event.req.method,
    +          headers: Object.fromEntries(event.req.headers.entries()),
    +        },
    +      })) + VITE_DEV_RECOVERY_SCRIPT,

    With VITE_DEV_RECOVERY_SCRIPT being:

    const VITE_DEV_RECOVERY_SCRIPT = `<script type="module">
      import { createHotContext } from "/@vite/client";
      let pending = false;
      async function reloadWhenServerRecovers() {
        if (pending) return;
        pending = true;
        for (const delay of [0, 100, 200, 400, 800]) {
          await new Promise(r => setTimeout(r, delay));
          const res = await fetch(location.href, {
            cache: "no-store",
            headers: { accept: "text/html" },
          }).catch(() => null);
          if (res && res.status < 500) return location.reload();
        }
        pending = false;
      }
      const hot = createHotContext("/@nitro/dev-error-page");
      hot.on("vite:beforeUpdate", reloadWhenServerRecovers);
      hot.on("vite:error", reloadWhenServerRecovers);
    </script>`;
  6. birkskyum commented on Jul 27, 2026

    @birkskyum
    Member

    Cross-linking a sibling case that turned up while looking at this: #2260.

    The report here is the eager path. app.tsx is imported eagerly, so a syntax error fails at handler level and you get an error page (Nitro's youch page, per the patch above). Route modules take a different path: they all go through lazy(), and there a syntax error produces no page at all. Solid's server-side lazy has no rejection handler, so the Suspense boundary never settles and renderToStream never calls end(). The shell is flushed and the connection then stays open indefinitely, so the browser shows a blank page and no overlay, because as far as it's concerned the page loaded fine.

    Root cause is upstream in Solid: solidjs/solid#2945. Tracked on the Start side in #2260, where there's a local workaround in withAssets that can be dropped once the Solid fix lands.

  7. birkskyum commented on Aug 17, 2026

    @birkskyum
    Member

    Retested on 2026-08-18 with:

    • @solidjs/start@2.0.0
    • nitro@3.0.260610-beta (the current npm latest)
    • solid-js@1.9.15
    • vite@8.2.1

    The status is unchanged for the eager app.tsx path when nitro() is installed:

    1. The app initially renders normally.
    2. Introducing a JSX syntax error in src/app.tsx navigates the browser to Nitro's HTTP 500 / Youch page.
    3. Correcting the file does not recover or reload the page (verified after waiting for the update).
    4. A manual reload immediately renders the corrected app.

    The published Nitro package still returns only await youch.toHTML(...) for an HTML development error response. I also checked current Nitro main at 4bfb35a; the same handler still has no /@vite/client or equivalent recovery hook. I could not find a matching Nitro issue or PR implementing recovery.

    The separate lazy-route failure tracked in #2260 / solidjs/solid#2945 is now fixed by solid-js@1.9.15 and #2260 has been closed. That fix does not affect this eager handler-level error path.

    Conclusion: keep this issue open. Updating Solid is not sufficient; the remaining blocker is still Nitro's development error page needing a Vite/HMR recovery mechanism (or equivalent polling/reload behavior).

  8. lxsmnsyc commented on Oct 13, 2026

    @lxsmnsyc
    Member

    Checked this on the 1.x line, since the original report is against v1 on Vinxi. The comments above cover v2.

    It still reproduces on 1.x. I used the bare fixture from the 1.x branch (vinxi 0.5.8) and followed the steps from the report in a browser:

    1. Make src/app.tsx invalid. The browser ends up on a 503 Server Unavailable page with no error overlay.
    2. Make the file valid again. The page stays on the 503 and does not recover.
    3. Reload by hand. The fixed app renders.

    Cause. The 503 page is Vinxi's dev error handler (vinxi/lib/dev-error.js). A syntax error in app.tsx makes ssrLoadModule fail on the SSR handler's module graph (entry-server → StartServer → app.tsx), so none of SolidStart's runtime code runs. Vinxi then sends a static HTML page without /@vite/client. The page has no HMR connection, so nothing tells it when the file is fixed.

    Why SolidStart 1.x cannot fix this cleanly.

    • Vinxi ignores Nitro's devErrorHandler option (the line that would read it is commented out in vinxi/lib/nitro-dev.js), so SolidStart cannot replace the error page through config.
    • The failure happens while loading SolidStart's own handler module, before any SolidStart code can catch it.
    • The only SolidStart-side workaround would be to point the SSR router at a dev-only wrapper that imports entry-server dynamically and renders its own recovery page. That changes how 1.x loads its handler, which is too large a change for the maintenance line to work around a Vinxi bug.

    The fix belongs in Vinxi's dev error page: it needs a Vite client, or a reload-when-the-server-recovers script like the one in the Nitro patch above. In v2 SolidStart owns the dev server, which is why the no-Nitro case could be fixed there.

    Workaround on 1.x: after fixing the file, reload the page by hand.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions