Skip to content

vite-plus bins conflict with oxfmt and oxlint bins #1482

Closed

Description

@nstepien

Describe the bug

vite-plus has oxfmt and oxlint bin files that should be referenced by related files in node_modules/.bin/

Image

But vite-plus also installs its oxfmt and oxlint dependencies, which have their own bin files, and those bin files are referenced in node_modules/.bin/ instead of the vite-plus bins.

Image Image Image

This breaks the oxc vscode extension when trying to use vite.config.ts as the configPath

Image

Not sure if this is only an issue with Windows and/or npm, either way the bin names should probably not conflict.

Reproduction

https://github.com/nstepien/vite-plus-bug

Steps to reproduce

  1. npm i vite-plus@latest
  2. look at the relevant oxfmt/oxlint files under node_modules/.bin/
  3. check if the formatter and linter work correctly in vscode

System Info

Environment:
  Version      25.9.0
  Source       default
  Source Path  C:\Users\Stepi\.vite-plus\config.json

Tool Paths:
  node  C:\Users\Stepi\.vite-plus\js_runtime\node\25.9.0\node.exe
  npm   C:\Users\Stepi\.vite-plus\js_runtime\node\25.9.0\npm.cmd
  npx   C:\Users\Stepi\.vite-plus\js_runtime\node\25.9.0\npx.cmd

vp v0.1.19

Local vite-plus:
  vite-plus  v0.1.19

Tools:
  vite             v8.0.8
  rolldown         v1.0.0-rc.16
  vitest           v4.1.4
  oxfmt            v0.45.0
  oxlint           v1.60.0
  oxlint-tsgolint  v0.21.1
  tsdown           v0.21.9

Environment:
  Package manager  npm vlatest
  Node.js          v25.9.0

`npm version` output:
{
  npm: '11.13.0',
  node: '25.9.0',
  acorn: '8.16.0',
  ada: '3.4.4',
  amaro: '1.1.8',
  ares: '1.34.6',
  brotli: '1.2.0',
  cldr: '48.0',
  icu: '78.2',
  lief: '0.17.0',
  llhttp: '9.3.1',
  merve: '1.2.2',
  modules: '141',
  napi: '10',
  nbytes: '0.1.3',
  ncrypto: '0.0.1',
  nghttp2: '1.68.0',
  nghttp3: '',
  ngtcp2: '',
  openssl: '3.5.5',
  simdjson: '4.5.0',
  simdutf: '7.3.3',
  sqlite: '3.51.3',
  tz: '2026a',
  undici: '7.24.4',
  unicode: '17.0',
  uv: '1.51.0',
  uvwasi: '0.0.23',
  v8: '14.1.146.11-node.25',
  zlib: '1.3.1-e00f703',
  zstd: '1.5.7'
}

Used Package Manager

npm

Logs

2026-04-26 21:21:35.001 [info] 2026-04-26T20:21:34.961695Z  WARN oxlint::lsp::server_linter: Failed to load config: Failed to parse config from d:/repos/vite-plus-bug\vite.config.ts

Validations

Activity

  1. added theissue type on Apr 26, 2026
  2. leaysgur commented on Apr 27, 2026

    @leaysgur
    Contributor

    I think I was able to reproduce it too, with npm and on macOS.

    # 🤔 Setup repro
    # git clone https://github.com/nstepien/vite-plus-bug.git
    # cd vite-plus-bug
    
    ❯ cat package.json
    {
      "private": true,
      "type": "module",
      "dependencies": {
        "vite-plus": "^0.1.19"
      }
    }
    

    With pnpm:

    ❯ pnpm i
    Packages: +45
    +++++++++++++++++++++++++++++++++++++++++++++
    Progress: resolved 123, reused 51, downloaded 0, added 45, done
    
    dependencies:
    + vite-plus 0.1.19
    
    Done in 965ms using pnpm v10.33.0
    
    ❯ cat node_modules/.bin/oxfmt
    #!/bin/sh
    basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
    
    case `uname` in
        *CYGWIN*|*MINGW*|*MSYS*)
            if command -v cygpath > /dev/null 2>&1; then
                basedir=`cygpath -w "$basedir"`
            fi
        ;;
    esac
    
    if [ -z "$NODE_PATH" ]; then
      export NODE_PATH="/Users/leaysgur/Sandbox/vite-plus-bug/node_modules/.pnpm/vite-plus@0.1.19_vite@8.0.10/node_modules/vite-plus/node_modules:/Users/leaysgur/Sandbox/vite-plus-bug/node_modules/.pnpm/vite-plus@0.1.19_vite@8.0.10/node_modules:/Users/leaysgur/Sandbox/vite-plus-bug/node_modules/.pnpm/node_modules"
    else
      export NODE_PATH="/Users/leaysgur/Sandbox/vite-plus-bug/node_modules/.pnpm/vite-plus@0.1.19_vite@8.0.10/node_modules/vite-plus/node_modules:/Users/leaysgur/Sandbox/vite-plus-bug/node_modules/.pnpm/vite-plus@0.1.19_vite@8.0.10/node_modules:/Users/leaysgur/Sandbox/vite-plus-bug/node_modules/.pnpm/node_modules:$NODE_PATH"
    fi
    if [ -x "$basedir/node" ]; then
      exec "$basedir/node"  "$basedir/../vite-plus/bin/oxfmt" "$@"
    else
      exec node  "$basedir/../vite-plus/bin/oxfmt" "$@"
    fi
    
    # 🤔 OK: our wrapper bin is installed
    
    ❯ ls -l node_modules/oxfmt
    "node_modules/oxfmt": No such file or directory (os error 2)
    
    # 🤔 OK: Not visible
    

    With npm:

    ❯ rm -rf node_modules
    
    ❯ npm i
    
    added 45 packages, and audited 46 packages in 631ms
    
    12 packages are looking for funding
      run `npm fund` for details
    
    found 0 vulnerabilities
    
    ❯ cat node_modules/.bin/oxfmt
    #!/usr/bin/env node
    
    import "../dist/cli.js";
    
    # 🤔 NG: our wrapper bin is NOT installed
    
    ❯ ls -l node_modules/oxfmt
    drwxr-xr-x@    - leaysgur 27 Apr 10:28 bin
    .rw-r--r--@  49k leaysgur 27 Apr 10:28 configuration_schema.json
    drwxr-xr-x@    - leaysgur 27 Apr 10:28 dist
    .rw-r--r--@ 1.1k leaysgur 27 Apr 10:28 LICENSE
    .rw-r--r--@ 2.8k leaysgur 27 Apr 10:28 package.json
    .rw-r--r--@ 2.3k leaysgur 27 Apr 10:28 README.md
    
    # 🤔 NG: It should not be there?
    

    The same happens with vp i w/ npm.

    @fengmk2 What was this supposed to look like in the first place? Usage with npm is broken from day 1...?

  3. jong-kyung commented on Apr 27, 2026

    @jong-kyung
    Collaborator

    I can reproduce this too. I think the root cause is dependency hoisting. 🤔

  4. fengmk2 commented on Apr 27, 2026

    @fengmk2
    Member

    @leaysgur It's quite possible that we only tested the pnpm scenario at that time. In that case, we can't use the bin wrapper anymore and need to detect vite-plus and use the actual vp bin instead. 😢

  5. leaysgur commented on Apr 28, 2026

    @leaysgur
    Contributor

    I tested a possible workaround that works on npm/pnpm/yarn without upstream changes:

    • Add oxlint/oxfmt to bundleDependencies so they get nested under node_modules/vite-plus/ instead of being hoisted
      • This keeps .bin/oxlint and .bin/oxfmt pointing at our wrapper bins
    • Mirror all @oxlint/binding-* and @oxfmt/binding-* as direct optionalDependencies on vite-plus
      • These are not resolved through bundleDependencies

    The catch is release complexity; ~38 binding entries to keep version-matched for every oxlint/oxfmt upgrade.

  6. fengmk2 commented on Apr 28, 2026

    @fengmk2
    Member

    @leaysgur If the project's own dependencies or indirect dependencies include oxlint and oxfmt, will it also cause similar issues under npm due to hoisting?

  7. leaysgur commented on Apr 28, 2026

    @leaysgur
    Contributor

    I think so. And that's still the case with pnpm today.

  8. fengmk2 commented on Apr 28, 2026

    @fengmk2
    Member

    @leaysgur Should we directly consider switching to a different solution and stop implementing it through a temporary bin wrapper? Similar to the vitest extension, we first detect whether it's a vite-plus project. If it is, we use the vp bin; if not, we use the oxlint|fmt bin.

  9. leaysgur commented on Apr 30, 2026

    @leaysgur
    Contributor

    (The reason I'm hesitant to make changes on the extension side (= the LSP consumer) is that, unlike Vitest, there are many other editors besides VS Code that oxapps need to support...)


    Summary:

    Unlike other sub-tools, only oxlint and oxfmt are bundled with Vite+ in a way that is visible externally (the presence of node_modules/oxlint|fmt).

    Because of this, if a user installs oxlint or oxfmt separately later, they end up using an arbitrary version instead.

    • You can verify this by noticing that the version displayed by vp -V differs from the one shown by vp lint|fmt -V
    • This causes the wrapper binaries for LSP, which were originally installed by vite-plus, to be overwritten (and broken)
    • This issue occurs regardless of the package manager being used

    Additionally, we've found that when using npm as the package manager, the vite-plus wrapper binaries aren't installed at all (the subject of this issue).

    Could we bundle these in a way that makes them invisible from the outside, just like the other tools?


    UPDATE: We decided to remove wrapper bin. Please follow #1557

  10. added this to the Beta milestone on May 18, 2026
  11. will-stone commented on May 28, 2026

    @will-stone

    Hi, is there a plan to release a new vite-plus every time an oxlint or oxfmt is released? I'm using vite-plus to build out my shared Oxlint/Oxfmt configs package and noticed it runs on older versions of Oxlint so doesn't include all the rules.

  12. fengmk2 commented on May 28, 2026

    @fengmk2
    Member

    @will-stone The current version release plan is that vite-plus will include these new versions in the following week after the new releases of oxlint/oxfmt.

  13. will-stone commented on May 28, 2026

    @will-stone

    Okay, thanks @fengmk2

  14. modified the milestones: Beta, RC on Jul 6, 2026
  15. nstepien commented on Sep 24, 2026

    @nstepien
    Author

    I guess the only blocker left is in oxc-vscode now?
    oxc-project/oxc-vscode#401 / oxc-project/oxc-vscode#384 / oxc-project/oxc-vscode#402

  16. leaysgur commented on Sep 25, 2026

    @leaysgur
    Contributor

    Thank you for tracking. 😉

    I've just released our IDE extensions, so now this issue can be closed.

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

Metadata

Metadata

Labels

bugSomething isn't working

Type

Fields

Priority

None yet

Effort

None yet

Target date

None yet

Start date

None yet

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions