Skip to content

@tanstack/devtools-vite 0.7.0 production build fails — code removal leaves invalid return () syntax #444

Description

@kimsagro1

TanStack Devtools version

0.7.0

Framework/Library version

react

Describe the bug and the steps to reproduce it

Bug Report

Describe the bug

After upgrading @tanstack/devtools-vite from 0.6.0 to 0.7.0, the production build fails. The plugin successfully detects and removes devtools code, but the transform leaves behind return (); — an empty parenthesized expression — which is a syntax error that rolldown rejects.

Steps to Reproduce

  1. Upgrade @tanstack/devtools-vite from 0.6.0 → 0.7.0
  2. Have a component where the entire return value is devtools content:
// src/lib/devtools/devtools.provider.tsx
import { TanStackDevtools } from "@tanstack/react-devtools";
import { FormDevtoolsPanel } from "@tanstack/react-form-devtools";
import { ReactQueryDevtoolsPanel } from "@tanstack/react-query-devtools";

export function DevtoolsProvider() {
  return (
      <TanStackDevtools
        plugins={[
          {
            name: "TanStack Query",
            render: <ReactQueryDevtoolsPanel />,
          },
          {
            name: "TanStack Form",
            render: <FormDevtoolsPanel />,
          },
        ]}
      />
  );
}
  1. Run vite build

Expected Behavior

Build succeeds. When the entire return expression is stripped, the transform should produce valid syntax — e.g. return null;.

Actual Behavior

The plugin removes the JSX but leaves the return ( and ); tokens intact, producing:

export function DevtoolsProvider() {
  return (
      );   // ← invalid empty parenthesized expression
}

Which causes the build to fail:

[@tanstack/devtools-vite] Removed devtools code from: /src/lib/devtools/devtools.provider.tsx
✗ Build failed in 708ms
error during build:
Build failed with 1 error:
[builtin:vite-transform] Empty parenthesized expression
   ╭─[ src/lib/devtools/devtools.provider.tsx:3:10 ]
   │
 3 │ ╭─▶   return (
 4 │ ├─▶       );
   │ │
   │ ╰──────────────
───╯

Environment

Version
@tanstack/devtools-vite 0.7.0 (regression from 0.6.0)
vite 8.0.13
OS Windows

Workaround

Pin back to @tanstack/devtools-vite@0.6.0, or wrap the return in a fragment so stripping the devtools node still leaves valid syntax:

export function DevtoolsProvider() {
  return (
    <>
    <TanStackDevtools
        plugins={[
          {
            name: "TanStack Query",
            render: <ReactQueryDevtoolsPanel />,
          },
          {
            name: "TanStack Form",
            render: <FormDevtoolsPanel />,
          },
        ]}
      />
    </>
  );
}

(Though this workaround shouldn't be necessary.)

Root Cause (suspected)

The code removal transform in 0.7.0 strips the JSX node inside return (...) but does not remove or replace the surrounding return ( ... ) wrapper. When the stripped node was the only child, this leaves return (); which is syntactically invalid. The fix should replace the emptied return with return null;.

Your Minimal, Reproducible Example - (Sandbox Highly Recommended)

https://stackblitz.com/edit/vitejs-vite-rug5ebyz?file=src%2Fmain.tsx

Screenshots or Videos (Optional)

Do you intend to try to help solve this bug with your own PR?

None

Terms & Code of Conduct

  • I agree to follow this project's Code of Conduct
  • I understand that if my bug cannot be reliable reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.

Activity

  1. github-actions commented on May 15, 2026

    @github-actions
    Contributor

    Thanks for the detailed report. To help us confirm and fix this quickly, could you share a minimal reproducible example (preferably a small repo or sandbox) that reproduces the build failure on a clean setup? A tiny repro with just the relevant provider/component and build config would be ideal.

  2. kimsagro1 commented on May 15, 2026

    @kimsagro1
    Author

    I have provided a reproducible example

  3. dstarosta commented on May 28, 2026

    @dstarosta

    I have the same problem.

  4. eikowagenknecht commented on Jun 7, 2026

    @eikowagenknecht

    Similar regression here. The proposed return null fix wouldn't cover it though.

    Our devtools element is guarded by && inside a JSX expression container:

    {!import.meta.env.VITE_DISABLE_DEVTOOLS && (
      <TanStackDevtools plugins={[/* ... */]} />
    )}

    After 0.7.0 strips it, the wrapper survives and leaves empty parens:

    {!import.meta.env.VITE_DISABLE_DEVTOOLS && (
      )}

    So it's not specific to return (...). Any wrapper whose only content was the devtools element breaks the same way (return (...), cond && (...), cond ? (...) : null). In dist/esm/remove-devtools.js the walk does s.remove(node.start, node.end) on just the JSXElement.

    The fix needs to replace/remove the enclosing expression with null, not only the inner element.

    The issue says staying on 0.6.0 is the workaround, but 0.6.1 also works.

  5. tomitheninja commented on Jun 8, 2026

    @tomitheninja

    Found an easy workaround:
    wrap in a fragment

    export function Devtools() {
      return (
    +    <>
    +      {
            <TanStackDevtools
               // ...
            />
    +      }
    +    </>
      );
    }
  6. eikowagenknecht commented on Jun 10, 2026

    @eikowagenknecht

    Can confirm this workaround works.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions