Skip to content

rive_native: runRiveNativeSetup assumes dart is on PATH → Android build fails (sh: dart: command not found) with FVM / IDE-launched builds / CI #646

Open

Description

@rubenvde

Submission checklist

  • I have confirmed the issue is present in the latest version of the rive Flutter package
  • I have searched the documentation and forums and could not find an answer
  • I have searched existing issues and this is not a duplicate

Description

What happens

Building an Android app that depends on rive (which pulls in rive_native) fails during the :rive_native:runRiveNativeSetup Gradle task:

sh: dart: command not found

FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':rive_native:runRiveNativeSetup'.
> Process 'command 'sh'' finished with non-zero exit value 127
Error: Gradle task assembleDevDebug failed with exit code 1

Environment

  • rive: 0.14.9 (latest)
  • rive_native: 0.1.9 (latest)
  • Flutter: 3.44.6 (stable), managed via FVM (.fvm/flutter_sdk symlink)
  • Host: macOS (Apple Silicon)
  • Trigger: build launched from an IDE (VS Code / Android Studio) and/or via FVM, where the pinned dart is not on the process PATH.

Root cause

rive_native/android/build.gradle (runRiveNativeSetup) shells out to bare dart and relies on it being on the inherited PATH:

// Use shell to find and execute dart (shell has access to PATH)
if (isWindows) {
    executable "cmd"
    args "/C", "dart", "run", "rive_native:setup", "--verbose", "-p", "android"
} else {
    executable "sh"
    args "-c", "dart run rive_native:setup --verbose -p android"
}

That assumption breaks in common setups:

  • macOS GUI-launched IDEs (VS Code/Android Studio opened from Dock/Finder) spawn build processes with a minimal PATH that omits dart entirely.
  • FVM / asdf / mise / puro — the correct dart (matching the SDK driving the build) isn't the one on PATH, if any is.
  • CI — dart frequently isn't on PATH.

It "works on my machine" only when a terminal with dart on PATH happens to spawn the build — and even then it may silently use a different Dart version than the one building the app.

Expected behavior

runRiveNativeSetup should invoke the Dart that ships with the Flutter SDK actually driving the build, not a PATH lookup. Flutter already hands the SDK path to Gradle — the same source of truth Flutter's
own Gradle plugin uses:

  • flutter.sdk in <app>/android/local.properties (canonical), and
  • the FLUTTER_ROOT environment variable (fallback).

(In flutter_tools/gradle, FlutterPlugin.kt reads FLUTTER_ROOT and flutter.sdk, erroring with "Define location with flutter.sdk in the local.properties file or with a FLUTTER_ROOT environment variable"
— exactly the resolution rive_native should reuse.)

Suggested fix

Resolve the Flutter SDK and call its dart directly instead of shelling out to bare dart:

def flutterRoot = {
    def props = new Properties()
    def lp = new File(project.rootProject.projectDir, "local.properties")
    if (lp.exists()) lp.withInputStream { props.load(it) }
    return props.getProperty("flutter.sdk") ?: System.getenv("FLUTTER_ROOT")
}()
def dartExe = isWindows ? "${flutterRoot}\\bin\\dart.bat" : "${flutterRoot}/bin/dart"

executable dartExe
args "run", "rive_native:setup", "--verbose", "-p", "android"

This works for FVM/asdf/mise, CI, and every IDE, removes the PATH dependency, and guarantees the setup runs on the same Dart version as the build.

Current workaround

Prepend the SDK's bin to PATH for the build. For VS Code we add it to each launch.json config:

"env":     { "PATH": "${workspaceFolder}/.fvm/flutter_sdk/bin:${env:PATH}" },
"windows": { "env": { "PATH": "${workspaceFolder}/.fvm/flutter_sdk/bin;${env:PATH}" } }

This shouldn't be necessary, the plugin has enough information to find the right dart itself.

Reproduction steps / code

  1. Make sure you don't have dart or flutter in your PATH
  2. Install fvm via brew install fvm
  3. Open your app project that has the rive: ^0.14.9 dependency
  4. Run fvm use 3.44.6
  5. In Vscode set the launch.json settings like so:
{
  "name": "Dev",
  "program": "lib/main.dart",
  "request": "launch",
  "type": "dart",
  "args": [
    "--flavor",
    "dev"
  ],
},
  1. Then launch the app on an Android device/emulator

Upload your reproduction files / stack trace

No response

Source .riv / .rev file

No response

Screenshots / video

Screenshot 2026-07-20 at 10.30.35.png

Rive Flutter package version

0.14.9

Flutter version

No flutter path so no flutter --version

Device

Android Emulator

OS version

Android 16

Additional context

No response

Activity

  1. rubenvde commented on Aug 3, 2026

    @rubenvde
    Author

    Sorry to bother you @HayesGordon, but this issue has been open for some time now. I think that is can be an easy fix. Do you have the time to look at it? I'd have opened a PR myself, but it seems like the rive_native package is still not open sourced.

  2. HayesGordon commented on Aug 3, 2026

    @HayesGordon
    Contributor

    Thanks for the ping @rubenvde, I missed this. We're about to make a new release, but I'll get this patched up for the next one.

  3. ziqq commented on Aug 13, 2026

    @ziqq

    Confirmed this is still reproducible with rive 0.14.11 / rive_native 0.1.11.

    The failure can appear intermittent because runRiveNativeSetup is skipped while prebuilt .so files exist under the cached rive_native package directory. After upgrading from rive_native 0.1.10 to 0.1.11, the new package directory did not contain those artifacts, so the setup task ran again and failed with:

    sh: dart: command not found
    Execution failed for task ':rive_native:runRiveNativeSetup'.
    

    Running the setup once with the Dart executable from the active Flutter SDK downloaded the Android artifacts. Subsequent builds then skipped the task and passed this stage again. This explains why an unchanged IDE/toolchain configuration may work for a long time and suddenly fail immediately after a dependency upgrade or package-cache cleanup.

    Resolving Dart from flutter.sdk in local.properties, with FLUTTER_ROOT as a fallback, would avoid this cache-dependent behavior and support FVM, mise, and other SDK managers without project-specific PATH workarounds.

  4. rubenvde commented on Sep 5, 2026

    @rubenvde
    Author

    A month later, any update on this? @HayesGordon

  5. added
    knownTriaged: understood and tracked on our side
    on Oct 19, 2026
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

    knownTriaged: understood and tracked on our side

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions