◉RORK LABJP
●GPT-6.1 SOL — Added to Rork's model menu (09-29) with Low, Medium and High effort; included on Pro and Max●SONNET 5.5 — Claude Sonnet 5.5 is selectable: strong at UI design and faster than Sonnet 5 (09-28)●SDK 58 — Expo SDK 58 is out of beta as of 10/15 (beta since 09/15). Check your dependencies before upgrading●SDK 58 ISSUE — Early reports include Android widgets not refreshing on a schedule and Stripe linking statically●OBSERVE — EAS Observe now records native crashes too (SDK 57.0.21 or later, 10/07)●NEW — My App Open Ad Only Showed When the App…●GPT-6.1 SOL — Added to Rork's model menu (09-29) with Low, Medium and High effort; included on Pro and Max●SONNET 5.5 — Claude Sonnet 5.5 is selectable: strong at UI design and faster than Sonnet 5 (09-28)●SDK 58 — Expo SDK 58 is out of beta as of 10/15 (beta since 09/15). Check your dependencies before upgrading●SDK 58 ISSUE — Early reports include Android widgets not refreshing on a schedule and Stripe linking statically●OBSERVE — EAS Observe now records native crashes too (SDK 57.0.21 or later, 10/07)●NEW — My App Open Ad Only Showed When the App…
Articles/App Dev
◇ App Dev/2026-10-24Intermediate

Could Not Find Method exec() on an EAS Android Build: Read the Script Line Before Your Own Code

An EAS Android build stops inside a .gradle file under node_modules with Could not find method exec(). Using a Sentry case as the starting point, here is the order I check things in, and a small shell script that pulls the culprit package out of the log.

eas-buildandroid4gradlesentrytroubleshooting74expo14

You bump the SDK, tidy a few dependencies, and send an Android build to EAS. The log turns red at the bottom and stops here.

FAILURE: Build failed with an exception.
 
* Where:
Script '/home/expo/workingdir/build/node_modules/@sentry/react-native/sentry.gradle' line: 127
 
> Could not find method exec() for arguments [...] on task ':app:createBundleReleaseJsAndAssets_SentryUpload_...' of type org.gradle.api.DefaultTask.

You haven't touched your own build.gradle, and yet something is "not found". It's the kind of moment where my hands stop moving.

What I'd like to say first: the line worth reading is not the final error, it's the Script '…' line: N two lines above it. It names the package and the line number outright.

This message matches the one reported in expo/expo issue #42494 (during the SDK 55 preview, filed in January 2026, now closed). As far as that page goes, it happened with @sentry/react-native 7.2.0 and Sentry fixed it in 7.3.0. The page doesn't explain the mechanism; the title only offers "Gradle 9 incompatibility" as the reading. What I verified myself is the log-parsing part below. I did not reproduce the EAS build itself, so please read it with that in mind.

Why the script line, not your app code

Gradle error text is long on task names and short on meaning. The Script '…' line: line, by contrast, tells you which file was executing when things fell over. If that path points into node_modules/, the cause is an installed package (and its version), not your app.

Gradle 9 also dropped the project-level exec() call that had been deprecated for a while, so an old-style script failing on a newer Gradle is the skeleton of this message. That's my understanding from the migration notes, not something I confirmed on a specific log. So before deciding "Gradle got newer", I collect facts in this order:

  1. Pull the package name out of the failing script path
  2. Look at the version actually installed
  3. Check whether the same symptom was reported and which version fixed it
  4. Raise the version and rebuild with the same dependency set

Steps 1 and 2: a small script to extract the package

Reading logs by eye gets tiring, so I wrote this. Save the log from the EAS page and pass it in; it prints the package, script, line, and symptom.

#!/usr/bin/env bash
# Usage: bash who-called-gradle.sh build.log
# Extract which node_modules script failed, and on which line, from a Gradle log
log="${1:?pass a log file}"
line=$(grep -m1 "^Script '" "$log") || { echo "No Script line found (the failure may be in your own build.gradle)"; exit 1; }
path=$(printf '%s' "$line" | sed -E "s/^Script '([^']+)'.*/\1/")
lno=$(printf '%s' "$line" | sed -E "s/.*line: ([0-9]+).*/\1/")
pkg=$(printf '%s' "$path" | sed -E 's#.*/node_modules/((@[^/]+/)?[^/]+)/.*#\1#')
echo "package : $pkg"
echo "script  : ${path##*/node_modules/}"
echo "line    : $lno"
grep -m1 -oE "Could not find method [a-zA-Z]+\(\)" "$log" | sed 's/^/symptom : /'
echo "next    : npm ls $pkg   # check the installed version"

Run against a sample log shaped like the one above (sample-eas.log), it printed:

package : @sentry/react-native
script  : @sentry/react-native/sentry.gradle
line    : 127
symptom : Could not find method exec()
next    : npm ls @sentry/react-native   # check the installed version

Given a file with no Script line (I tried one containing just plain error), it says the failure may be in your own build.gradle and exits with code 1. I added that branch because the thing I most wanted to avoid was a script that prints nothing and looks like it succeeded.

The sample log is my own reconstruction from the issue text. If your real EAS log differs in line numbers or surrounding output, adjust the grep patterns to match.

Step 3: has this been reported, and which version fixed it?

Once you have the package name, search that repository's issues, or Expo's. In this case the fix was reported in @sentry/react-native 7.3.0, so an installed 7.2.0 is a match.

One caution: the version Expo recommends (what npx expo install pulls in) and the version the package fixed things in can disagree. The reporter pointed out that Expo's own recommended version was the affected 7.2.0. "I installed it with expo install, so it's fine" doesn't always hold.

# Which version is installed (and is it only a transitive dependency?)
npm ls @sentry/react-native
 
# Show drift from what Expo expects
npx expo install --check

The second command lists mismatched packages and offers to fix them. Before accepting, I save the output so I can read back what changed.

Step 4: raise the version and send the same build again

Once you know the fixed version, install it explicitly.

npx expo install @sentry/react-native@7.3.0   # example: the first version with the fix
npx expo-doctor                                # did the mismatches grow?
eas build --platform android --profile production

I pinned 7.3.0 because the issue named it as the first fixed version. Jumping to the latest is an option, but it can move the mismatch somewhere else. I'd rather confirm the build passes on the smallest fix first, and treat "should I go further" as a separate decision.

What I still don't know

As an indie developer who ships Android release builds by hand, I often have to move forward with gaps like these. Three things are unverified in this write-up.

Not verifiedWhy
That I reproduced the same error on EASI didn't. Only the log-parsing script was run, against a sample log
Which Gradle 9 change is the direct causeThe issue page doesn't explain the mechanism; I'm quoting the title's reading
Whether other Gradle scripts keep the same old styleI only looked at Sentry

The third one nags at me. If it happened with Sentry, other packages may still carry the same old call and simply haven't been stepped on yet. After each SDK bump, a quick grep -rn "exec(" node_modules --include=*.gradle might let you notice before a production build does.

Where I draw the line

With build failures, fixing the last red line tends to be the longer way around.

Read the line that says where it fell, not the line that says what it felt. Versions only enter the conversation once that line has pointed at a package.

As a first step, if you still have a recent failed log, run it through the script once. If a package name comes out, half the work is done.

For how dependency versions drift without anyone noticing, I also wrote up a count of how far Expo's bundled modules slide across patch releases.

Sources:

Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

◇ App Dev2026-10-15
When adjustsFontSizeToFit Shrinks Just One Row, Suspect the Box Height, Not the String
Only the 10th row of a list drops to 4pt on iOS, though the data and strings are fine. I read the Yoga rounding and font-fit sources, then counted how often the box comes up short in Node.
◇ App Dev2026-10-14
App Review Says "Guideline 2.1, Blank Screen": Three Places to Look in an Expo Release Build
It opens fine in TestFlight, yet review rejects it for a blank screen. Here is the order I check things in an Expo + EAS release build: which environment holds your variables, secret visibility during config resolution, and what the reviewer's device does differently.
⬡ Dev Tools2026-10-23
Failed to resolve plugin for module: Check the Spelling, the Install, the File, Then the Contents
You add one line to plugins in app.json and Expo stops with PluginError: Failed to resolve plugin for module. I reproduced the causes behind that one message in a blank Expo SDK 58 project and put them in the order I now check them, using a single command.