Skip to content

Incorrect Dart executable path resolution in sandboxed environments like Nix #2698

@fusion44

Description

@fusion44

Description

The logic for locating the dart executable within webdev and build_daemon makes assumptions about the Dart SDK directory structure that do not hold true when running as a compiled executable in a sandboxed environment like Nix.

The current implementation determines the path to the dart executable by traversing up from the path of the currently running executable (Platform.resolvedExecutable). This assumes a standard SDK layout where the application's executable is in a bin directory two levels below the SDK root. This assumption fails in environments like Nix, where the directory structure is different, leading to an incorrect path for the dart binary.

Context: How jaspr uses webdev

The jaspr build command utilizes the webdev package to compile its web assets. Specifically, it calls webdev's connectClient function to start and communicate with the build_runner daemon. It is during this process that webdev (and its dependency, build_daemon) attempts to locate the Dart SDK to start the daemon process, triggering the bug described above. The failure to correctly locate the dart executable prevents the build daemon from starting, which halts the entire jaspr build process.

Problematic Code

The following code contains the flawed logic:

/// The path to the root directory of the SDK.

Debugging Output

The following log output from within a Nix build environment clearly demonstrates the issue:

1 --- Debugging dart path resolution ---
2 Platform.resolvedExecutable: /nix/store/gx9i2rvqb3mjlhb2wxznr1y4ip42qaz9-jaspr-v0.21.3-dev/bin/jaspr
3 p.dirname(p.dirname(Platform.resolvedExecutable)): /nix/store/gx9i2rvqb3mjlhb2wxznr1y4ip42qaz9-jaspr-v0.21.3-dev
4 Checking for version file at: /nix/store/gx9i2rvqb3mjlhb2wxznr1y4ip42qaz9-jaspr-v0.21.3-dev/version
5 Version file exists: false
6 _sdkDir: /nix/store/gx9i2rvqb3mjlhb2wxznr1y4ip42qaz9-jaspr-v0.21.3-dev
7 Constructed dartPath: /nix/store/gx9i2rvqb3mjlhb2wxznr1y4ip42qaz9-jaspr-v0.21.3-dev/bin/dart
8 --- End of debugging dart path resolution ---

This output shows that:

  1. Platform.resolvedExecutable correctly points to the compiled application binary.
  2. The code incorrectly assumes the Dart SDK root is two directories above this binary.
  3. The check for a version file at this location fails, confirming the incorrect SDK path.
  4. The final dartPath is constructed within this incorrect directory, resulting in a path that does not exist and causing a
    ProcessException: No such file or directory.

Suggested Solution

The mechanism for locating the dart executable should be made more robust. Instead of relying on a fragile directory structure relative to the running executable, the process should simply execute dart and depend on the PATH environment variable to resolve the correct binary. This is a more portable approach that will work correctly across standard installations, Docker containers, and Nix environments.

The code responsible for starting the daemon process should be modified to use 'dart' as the executable, rather than constructing an absolute path based on these flawed assumptions.

Alternatively, let the caller override the dart executable path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2A bug or feature request we're likely to work onpackage:webdevtype-bugIncorrect behavior (everything from a crash to more subtle misbehavior)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions