Skip to content

Fails to build in bun-only environment when using virtualRouteConfig #6061

Closed

Description

@willhoney7

Which project does this relate to?

Router

Describe the bug

// vite.config.ts
 tanstackStart({
    router: {
        virtualRouteConfig: 'src/routes.ts',
    },
}),

When using virtualRouteConfig with tanstack/start, loadConfigFile uses tsx behind the scenes to load the config file. The problem is that tsx is node specific and doesn't work with bun.

Image

The hacky solution is to make sure your environment also has node installed. (So I've updated our Dockerfile to install node before running vite build, but then it continues to use bun to serve the server).

I am unsure what the full solution should be... change how the virtualRouteConfig gets loaded? add a "bun" flag?

Your Example Website or App

I could build a full reproduction but it would take a lot of time when the issue is easy to see in the code (it uses tsx!)

Steps to Reproduce the Bug or Issue

  • use virtualRouteConfig and try to build with only bun.

Expected behavior

I would expect tanstack/start to work with bun when using virtualRouteConfig.

Screenshots or Videos

No response

Platform

  • Router / Start Version: 1.134.10 (but the issue is there in latest)
  • OS: mac
  • Browser: n/a
  • Browser Version: n/a
  • Bundler: vite
  • Bundler Version: 6

Additional context

No response

Activity

  1. coderabbitai commented on Dec 10, 2025

    @coderabbitai
    Contributor

    📝 CodeRabbit Plan Mode

    Generate an implementation plan and agent prompts for this issue.

    ✅ Successfully generated implementation plan.

    💡 Use @coderabbitai <feedback> to replan

    Examples

    🔗 Similar Issues

    Related Issues

    🔗 Related PRs

    #5422 - fix(router-devtools-core): actually bundle solid [merged]
    #5816 - docs(solid-start): start-bun example [merged]
    #5847 - docs(solid-start): start-large example [merged]
    #5849 - docs(solid-start): start-tailwind-v4 [merged]

    👤 Suggested Assignees

    • birkskyum
    • harrytran998
    • akawahuynh
    • benmccann

    🧪 Issue enrichment is currently in early access.

    To disable automatic issue enrichment, add the following to your .coderabbit.yaml:

    issue_enrichment:
      auto_enrich:
        enabled: false
  2. schiller-manuel commented on Dec 10, 2025

    @schiller-manuel
    Collaborator

    for now you should be able to import the config yourself and pass it in instead of the filename

  3. willhoney7 commented on Dec 10, 2025

    @willhoney7
    Author

    for now you should be able to import the config yourself and pass it in instead of the filename

    oh. that is a much better solution! thank you!

    Maybe passing in a file path should be deprecated and the docs should guide towards passing in the route config object itself?

  4. coderabbitai commented on Dec 10, 2025

    @coderabbitai
    Contributor

    Implementation Plan

    Approach

    Enable TanStack Start's virtualRouteConfig feature to work in Bun runtime by making the config file loading mechanism runtime-aware, allowing it to use Bun's native TypeScript import instead of the Node-specific tsx loader.

    Observations

    The router-generator package provides utilities for generating TanStack Router route trees from both physical file system structures and virtual route configurations. The virtual route config loader (loadConfigFile.ts) currently uses tsx's tsImport API to dynamically load TypeScript configuration files at runtime. This function is used by both virtual and physical route node generators when loading external or inline route configuration files. The codebase currently assumes a Node.js runtime and uses Node-specific APIs (node:fs, node:path, node:url) throughout.

    Assumptions
    Assumption 1: Runtime Detection Method

    Options Considered:

    • Check typeof Bun !== "undefined" - requires bun-types to avoid TypeScript errors
    • Check process.versions.bun - safer in TypeScript environments and more idiomatic

    Chosen Option: Use process.versions.bun for detection

    Rationale: This approach is TypeScript-safe, doesn't require additional type definitions, and aligns with standard Node.js version detection patterns. Developers familiar with Node.js will recognize this pattern immediately.

    Assumption 2: Scope of Runtime Support

    Options Considered:

    • Add support for Bun only
    • Add abstraction layer for multiple runtimes (Bun, Deno, Node)

    Chosen Option: Focus solely on Bun support for now

    Rationale: The ticket specifically requests Bun support, and adding a more complex abstraction layer would be over-engineering. If Deno or other runtime support is needed later, the runtime detection pattern can be extended following the same approach established here.

    💡 User Tips

    Regenerate the plan with different choices with @coderabbitai <feedback>.

    Plan

    Add Bun Runtime Support to Config File Loading

    This phase modifies the config file loading mechanism to detect and handle both Node.js and Bun runtimes, ensuring the virtualRouteConfig feature works in both environments without requiring Node.js installation in Bun-only environments.

    Task 1: Add Runtime Detection Logic

    Implement runtime detection to determine whether code is executing in Bun or Node.js environment.

    • Add conditional check using process.versions.bun at the start of loadConfigFile function in packages/router-generator/src/filesystem/virtual/loadConfigFile.ts
    • The check should determine which import strategy to use without adding external dependencies
    Task 2: Implement Dual Import Strategy

    Create separate code paths for Bun's native TypeScript import and Node.js tsx import.

    • For Bun runtime: Use native import() function with the file URL, which Bun handles natively without requiring tsx
    • For Node.js runtime: Preserve existing tsx tsImport logic to maintain backward compatibility
    • Both paths should convert file paths to URLs using pathToFileURL from node:url
    • Both paths must return the same module exports object structure to ensure consistent behavior for downstream consumers
    Task 3: Ensure Error Handling Consistency

    Update error handling to provide clear feedback regardless of runtime.

    • Catch and handle import failures from both the native import() (Bun) and tsImport (Node) paths
    • Ensure error messages indicate which runtime was detected if import fails
    • Maintain the existing error contract expected by getRouteNodes.ts in both virtual and physical filesystem modules
    🤖 Prompt for AI agents
    Modify the config file loading mechanism to support both Bun and Node.js
    runtimes, enabling virtualRouteConfig to work in Bun environments.
    
    In `packages/router-generator/src/filesystem/virtual/loadConfigFile.ts`:
    - Add runtime detection at the start of `loadConfigFile` using
    `process.versions.bun` check
    - Implement conditional import strategy: use native `import()` with
    `pathToFileURL` for Bun runtime, preserve existing tsx `tsImport` for Node.js
    - Ensure both paths convert file paths to URLs and return consistent module
    exports structure
    - Add error handling for both import paths with runtime-specific error messages
    - Maintain backward compatibility and existing error contract for downstream
    consumers
    

    🚀 Next Steps

    🤖 All AI agent prompts combined
    Modify the config file loading mechanism to support both Bun and Node.js
    runtimes, enabling virtualRouteConfig to work in Bun environments.
    
    In `packages/router-generator/src/filesystem/virtual/loadConfigFile.ts`:
    - Add runtime detection at the start of `loadConfigFile` using
    `process.versions.bun` check
    - Implement conditional import strategy: use native `import()` with
    `pathToFileURL` for Bun runtime, preserve existing tsx `tsImport` for Node.js
    - Ensure both paths convert file paths to URLs and return consistent module
    exports structure
    - Add error handling for both import paths with runtime-specific error messages
    - Maintain backward compatibility and existing error contract for downstream
    consumers
    
    💡 Iterate on the plan with: @coderabbitai <feedback>
    Example Feedback
    - @coderabbitai You can skip phase 3. Add a simple unit test case for phase 2.
    - @coderabbitai For assumption 1 go ahead with option 3 and replan.
    
  5. schiller-manuel commented on Apr 25, 2026

    @schiller-manuel
    Collaborator

    migrated to jiti now

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