Skip to content

Dart LSP fails on Windows: 'Command not found' despite dart being in PATH #6861

@ravergurl

Description

@ravergurl

Description

The Dart LSP integration fails on Windows with "Command not found: dart" even when:

  1. dart is correctly installed and in PATH
  2. Bun.which('dart') returns a valid executable path
  3. The executable can be spawned successfully

Environment

  • OS: Windows 10/11
  • opencode version: 1.1.1
  • Dart SDK: 3.5.4

Steps to Reproduce

  1. Install Dart SDK on Windows (via Flutter or standalone)
  2. Verify dart --version works in terminal
  3. Run lsp_diagnostics on any .dart file

Expected Behavior

Dart LSP server starts and returns diagnostics.

Actual Behavior

Error: LSP server 'dart' is configured but NOT INSTALLED.

Command not found: dart

To install:
  Included with Dart SDK

Investigation Findings

Verification that dart works:

# Bun.which finds dart correctly
bun -e "console.log(Bun.which('dart'))"
# Output: C:\Users\peopl\bin\dart.exe

# dart runs fine
dart --version
# Output: Dart SDK version: 3.5.4

# Language server works
dart language-server --help
# Output: (help text displayed)

# Spawn without shell works
bun -e "const {spawn} = require('child_process'); const p = spawn(Bun.which('dart'), ['--version']); p.stdout.on('data', d => console.log(d.toString()))"
# Output: Dart SDK version: 3.5.4

Config override doesn't help:

Added to ~/.config/opencode/opencode.jsonc:

"lsp": {
  "dart": {
    "command": ["cmd.exe", "/c", "C:\Users\peopl\bin\dart.exe", "language-server", "--lsp"],
    "extensions": [".dart"]
  }
}

The LSP still reports "Command not found" - the config command override is being ignored during the availability check.

Root Cause Analysis

The issue appears to be in packages/opencode/src/lsp/server.ts. The Dart LSP config does:

export const Dart: Info = {
  id: "dart",
  extensions: [".dart"],
  root: NearestRoot(["pubspec.yaml", "analysis_options.yaml"]),
  async spawn(root) {
    const dart = Bun.which("dart")
    if (!dart) {
      log.info("dart not found, please install dart first")
      return
    }
    return {
      process: spawn(dart, ["language-server", "--lsp"], {
        cwd: root,
      }),
    }
  },
}

Two issues:

  1. The "installed" check happens before config command override is applied
  2. Even when Bun.which("dart") succeeds, something in the availability check fails

Proposed Fix

Option 1: Add shell: true for Windows:

process: spawn(dart, ["language-server", "--lsp"], {
  cwd: root,
  shell: process.platform === "win32",
}),

Option 2: Respect config command override during availability check - if user provides a custom command in config, skip the Bun.which check.

Related

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions