title: React Native build error: Text must not be null or empty
body: <p>My Jenkins build has given me the following error:</p>
  <pre><code>13:18:22 FAILURE: Build failed with an exception.
  13:18:22 
  13:18:22 * Where:
  13:18:22 Script '/Users/abcd/Jenkins/Jenkins-Workspaces/ABCD/ABCDL/node_modules/@react-native-community/cli-platform-android/native_modules.gradle' line: 190
  13:18:22 
  13:18:22 * What went wrong:
  13:18:22 A problem occurred evaluating settings 'AppName'.
  13:18:22 &gt; Text must not be null or empty
  13:18:22 
  </code></pre>
  <p>It seems the problem is with the <code>@react-native-community/cli-platform</code> node module, but reading over this closed issue:
  <a href="https://github.com/facebook/react-native/issues/25479" rel="nofollow noreferrer">https://github.com/facebook/react-native/issues/25479</a></p>
  <p>its unclear to me what exactly is the proposed and final solution to this.</p>
  <p>There is a recommendation on a fix that is more straightforward in this react-native issue:
  <a href="https://github.com/facebook/react-native/issues/25822" rel="nofollow noreferrer">https://github.com/facebook/react-native/issues/25822</a></p>
  <p>but my error is not complaining about that line.</p>
  <p>As far as installing <code>@react-native-community/cli</code> I believe I already have it inside my <code>package-lock.json</code> file:</p>
  <pre><code>&quot;react-native&quot;: {
        &quot;version&quot;: &quot;0.60.4&quot;,
        &quot;resolved&quot;: &quot;https://registry.npmjs.org/react-native/-/react-native-0.60.4.tgz&quot;,
        &quot;integrity&quot;: &quot;sha512-WE41lbGQjnzM9srIFtMDtMJkQAvk95iZwuFvAxl68s80bkYa7Ou9sGFHpeYIV6cY8yHtheCSo5q6YMxhdfkdOw==&quot;,
        &quot;requires&quot;: {
          &quot;@babel/runtime&quot;: &quot;^7.0.0&quot;,
          &quot;@react-native-community/cli&quot;: &quot;^2.0.1&quot;,
          &quot;@react-native-community/cli-platform-android&quot;: &quot;^2.0.1&quot;,
          &quot;@react-native-community/cli-platform-ios&quot;: &quot;^2.0.1&quot;,
  </code></pre>
  <p>Others mentioned something about <code>app/build.gradle</code>, here is the relevant part of mine:</p>
  <pre><code>// Run this once to be able to run the application with BUCK
  // puts all compile dependencies into folder libs for BUCK to use
  task copyDownloadableDepsToLibs(type: Copy) {
      from configurations.compile
      into 'libs'
  }
  
  apply from: file(&quot;../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle&quot;); applyNativeModulesAppBuildGradle(project)
  </code></pre>
  <p>Mention was also made of <code>android/settings.gradle</code>, this one is mine:</p>
  <pre><code>rootProject.name = 'NFIBEngage'
  include ':react-native-device-info'
  project(':react-native-device-info').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-device-info/android')
  include ':appcenter-crashes'
  project(':appcenter-crashes').projectDir = new File(rootProject.projectDir, '../node_modules/appcenter-crashes/android')
  include ':appcenter-analytics'
  project(':appcenter-analytics').projectDir = new File(rootProject.projectDir, '../node_modules/appcenter-analytics/android')
  include ':appcenter'
  project(':appcenter').projectDir = new File(rootProject.projectDir, '../node_modules/appcenter/android')
  include ':react-native-webview'
  project(':react-native-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview/android')
  apply from: file(&quot;../node_modules/@react-native-community/cli-platform-android/native_modules.gradle&quot;); applyNativeModulesSettingsGradle(settings)
  include ':app'
  </code></pre>
  <p>From what I have gathered here:</p>
  <p><a href="https://react-native-community.github.io/upgrade-helper/?from=0.53.3&amp;to=0.60.4" rel="nofollow noreferrer">https://react-native-community.github.io/upgrade-helper/?from=0.53.3&amp;to=0.60.4</a></p>
  <p>The above files are correct.</p>
  <p>So what exactly is wrong here and how do I fix it?</p>
  <p>In terms of <code>node_modules/@react-native-community/cli-platform-android/native_modules.gradle line 190</code> is this one:</p>
  <pre><code>def json = new JsonSlurper().parseText(reactNativeConfigOutput)
  </code></pre>
  <p>Could the problem be with how I wrote index.js file:</p>
  <pre><code>/**
   * @format
   */
  
  import { AppRegistry } from &quot;react-native&quot;;
  // old config code
  import KeyboardManager from &quot;react-native-keyboard-manager&quot;;
  // old config code ^^^
  import NFIBEngage from &quot;./App&quot;;
  import { name as appName } from &quot;./app.json&quot;;
  
  // old config code
  import { Sentry } from &quot;react-native-sentry&quot;;
  
  Sentry.config(
    &quot;https://asdf@sentry.io/123456677&quot;
  ).install();
  
  KeyboardManager.setToolbarPreviousNextButtonEnable(true);
  // old config code ^^^
  
  AppRegistry.registerComponent(&quot;NFIBEngage&quot;, () =&gt; NFIBEngage);
  </code></pre>
  <p>Is <code>AppRegistry.registerComponent()</code> written correctly?</p>
  <p>I ran the Jenkins script locally, which I believe is this script right here:</p>
  <pre><code>import fs from &quot;fs-extra&quot;;
  import eachSeries from &quot;async/eachSeries&quot;;
  import { exec } from &quot;child_process&quot;;
  import { androidDirectory } from &quot;../../app.json&quot;;
  import { resolveFromRoot, distDir, createLogger } from &quot;../build&quot;;
  
  const logger = createLogger(&quot;android&quot;);
  
  const APK_PATTERN = /release\.apk$/i;
  
  function copyArtifactsToDist() {
    logger.logHeader(&quot;Copying APK to Dist&quot;, { repeatChar: &quot;=&quot; });
    const baseDir = `${androidDirectory}/app/build/outputs/apk`;
  
    const allFlavs = [&quot;dev&quot;, &quot;qa&quot;, &quot;ua&quot;, &quot;prod&quot;];
    const branchName = process.env.GitVersion_BranchName || &quot;&quot;;
    const buildFlavour = branchName.startsWith(&quot;release/&quot;) ? allFlavs : [&quot;dev&quot;];
    const envs = {
      dev: &quot;INT&quot;,
      qa: &quot;QA&quot;,
      ua: &quot;UA&quot;,
      prod: &quot;&quot;
    };
  
    buildFlavour
      .map(env =&gt; {
        const apkOutputDir = resolveFromRoot(`${baseDir}/${env}/release`);
        return {
          apkOutputDir,
          env
        };
      })
      .forEach(({ apkOutputDir, env }) =&gt; {
        const src = `${apkOutputDir}/app-${env}-release.apk`;
        //prettier-ignore
        const binaryName = env === 'prod' ? 'ENGAL.apk' : `ENGAL-${envs[env]}.apk`;
        const dest = `${distDir}/${binaryName}`;
        fs.copy(src, dest, (err: Error) =&gt; {
          if (err) {
            logger.error(err);
          }
        });
      });
  }
  
  function run() {
    logger.logHeader(&quot;Starting Android Builds&quot;, { repeatChar: &quot;#&quot; });
    const flavours = [
      {
        endpoint: &quot;dv&quot;,
        flavour: &quot;Dev&quot;,
        appcenterKey: &quot;&lt;hashKeys&gt;&quot;
      },
      {
        endpoint: &quot;qa&quot;,
        flavour: &quot;Qa&quot;,
        appcenterKey: &quot;&lt;hashKeys&gt;&quot;
      },
      {
        endpoint: &quot;ua&quot;,
        flavour: &quot;Ua&quot;,
        appcenterKey: &quot;&lt;hashKeys&gt;&quot;
      },
      {
        endpoint: &quot;prod&quot;,
        flavour: &quot;Prod&quot;,
        appcenterKey: &quot;&lt;hashKeys&gt;&quot;
      }
    ];
  
    const versionCode = process.env.Build || 1;
    const release = process.env.GitVersion_MajorMinorPatch || &quot;1.0.0&quot;;
    const fullAppVersion = `${release}-${versionCode}`;
  
    const devFlav = flavours.find(f =&gt; f.flavour.toLocaleLowerCase() === &quot;dev&quot;);
  
    const branchName = process.env.GitVersion_BranchName || &quot;&quot;;
    const buildFlavour = branchName.startsWith(&quot;release/&quot;) ? flavours : [devFlav];
  
    eachSeries(
      buildFlavour,
      (f, callback) =&gt; {
        //prettier-ignore
        logger.logHeader(
          `starting gradle assemble${f.flavour}Release with flag - versionName=${fullAppVersion} -PversionCode=${versionCode}`,
          {repeatChar: '-'}
        );
  
        const engaInfo = `ENGAGE_VERSION=${fullAppVersion}`;
        const engaEndpoint = `ENGAGE_ENDPOINT=${f.endpoint}`;
        const engaCenter = `APPCENTER_KEY=${f.appcenterKey}`;
        const engaPlatform = &quot;APPCENTER_PLATFORM=android&quot;;
        //prettier-ignore
        const prepare = `${engaEndpoint} ${engaCenter} ${engaInfo} ${engaPlatform} npm run setup`;
        const cd = `cd ${androidDirectory}`;
        //prettier-ignore
        const releaseCmd = `./gradlew assemble${f.flavour}Release -PversionName=${fullAppVersion} -PversionCode=${versionCode} &amp;&amp; cd ..`;
  
        exec(`${prepare} &amp;&amp; ${cd} &amp;&amp; ${releaseCmd}`, err =&gt; {
          if (err) {
            return callback(err);
          }
  
          logger.logHeader(`${f.flavour} Android Build Successful!`, {
            repeatChar: &quot;#&quot;
          });
          logger.close();
          callback(null);
        });
      },
      error =&gt; {
        if (error) {
          logger.logHeader(&quot;Android Builds Failed!&quot;, {
            repeatChar: &quot;#&quot;
          });
          logger.error(error);
          logger.close();
        }
        copyArtifactsToDist();
      }
    );
  }
  
  run();
  </code></pre>
  <p>via <code>npm run build</code> and locally I got this error:</p>
  <pre><code>FAILURE: Build failed with an exception.
  
  * What went wrong:
  Task 'assembleDevRelease' not found in root project 'AppName'. Some candidates are: 'assembleRelease'.
  </code></pre>
  <p>Are these related errors? Anyone experienced with React Native builds?</p>
  <p>As suggested, I looked into my <code>android/app/build.gradle</code> file for <code>productFlavors</code> and noticed that indeed they were missing between here:</p>
  <pre><code>buildTypes {
          debug {
              signingConfig signingConfigs.debug
          }
          release {
              // Caution! In production, you need to generate your own keystore file.
              // see https://facebook.github.io/react-native/docs/signed-apk-android.
              signingConfig signingConfigs.debug
              minifyEnabled enableProguardInReleaseBuilds
              proguardFiles getDefaultProguardFile(&quot;proguard-android.txt&quot;), &quot;proguard-rules.pro&quot;
          }
      }
  
      // applicationVariants are e.g. debug, release
      applicationVariants.all { variant -&gt;
          variant.outputs.each { output -&gt;
              // For each separate APK per architecture, set a unique version code as described here:
              // https://developer.android.com/studio/build/configure-apk-splits.html
              def versionCodes = [&quot;armeabi-v7a&quot;: 1, &quot;x86&quot;: 2, &quot;arm64-v8a&quot;: 3, &quot;x86_64&quot;: 4]
              def abi = output.getFilter(OutputFile.ABI)
              if (abi != null) {  // null for the universal-debug, universal-release variants
                  output.versionCodeOverride =
                          versionCodes.get(abi) * 123456 + defaultConfig.versionCode
              }
  
          }
      }
  </code></pre>
  <p>So I added it like so:</p>
  <pre><code>buildTypes {
          debug {
              signingConfig signingConfigs.debug
          }
          release {
              // Caution! In production, you need to generate your own keystore file.
              // see https://facebook.github.io/react-native/docs/signed-apk-android.
              signingConfig signingConfigs.debug
              minifyEnabled enableProguardInReleaseBuilds
              proguardFiles getDefaultProguardFile(&quot;proguard-android.txt&quot;), &quot;proguard-rules.pro&quot;
          }
      }
  
      productFlavors {
        dev {
          resValue &quot;string&quot;, &quot;app_name&quot;, getAppName(&quot;INT&quot;)
          resValue &quot;string&quot;, &quot;link_launcher&quot;, getLauncher(&quot;dv&quot;)
          applicationIdSuffix &quot;.dv&quot;
          manifestPlaceholders = [onesignal_app_id: &quot;&lt;hash_id&gt;&quot;,
                                  onesignal_google_project_number: &quot;123456789&quot;]
        }
        qa {
          resValue &quot;string&quot;, &quot;app_name&quot;, getAppName(&quot;QA&quot;)
          resValue &quot;string&quot;, &quot;link_launcher&quot;, getLauncher(&quot;qa&quot;)
          applicationIdSuffix &quot;.qa&quot;
          manifestPlaceholders = [onesignal_app_id: &quot;&lt;hash_id&gt;&quot;,
                                  onesignal_google_project_number: &quot;123456789&quot;]
        }
        ua {
          resValue &quot;string&quot;, &quot;app_name&quot;, getAppName(&quot;UA&quot;)
          resValue &quot;string&quot;, &quot;link_launcher&quot;, getLauncher(&quot;ua&quot;)
          applicationIdSuffix &quot;.ua&quot;
          manifestPlaceholders = [onesignal_app_id: &quot;&lt;hash_id&gt;&quot;,
                                  onesignal_google_project_number: &quot;123456789&quot;]
        }
        prod {
          resValue &quot;string&quot;, &quot;app_name&quot;, getAppName()
          resValue &quot;string&quot;, &quot;link_launcher&quot;, getLauncher()
          manifestPlaceholders = [onesignal_app_id: &quot;&lt;hash_id&gt;&quot;,
                                  onesignal_google_project_number: &quot;601125149914&quot;]
        }
      }
  
      // applicationVariants are e.g. debug, release
      applicationVariants.all { variant -&gt;
          variant.outputs.each { output -&gt;
              // For each separate APK per architecture, set a unique version code as described here:
              // https://developer.android.com/studio/build/configure-apk-splits.html
              def versionCodes = [&quot;armeabi-v7a&quot;: 1, &quot;x86&quot;: 2, &quot;arm64-v8a&quot;: 3, &quot;x86_64&quot;: 4]
              def abi = output.getFilter(OutputFile.ABI)
              if (abi != null) {  // null for the universal-debug, universal-release variants
                  output.versionCodeOverride =
                          versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
              }
  
          }
      }
  </code></pre>
  <p>The <code>buildTypes</code> is looking a bit different than the original legacy <code>buildTypes</code> so I am not sure if that's okay, but at any rate I then ran <code>npm run build</code> again locally and got this error:</p>
  <pre><code>* Where:
  Build file '/Users/danale/Projects/NFIBEngage/android/app/build.gradle' line: 168
  
  * What went wrong:
  A problem occurred evaluating project ':app'.
  &gt; Could not find method getAppName() for arguments [INT] on ProductFlavor_Decorated{name=dev, dimension=null, minSdkVersion=null, targetSdkVersion=null, renderscriptTargetApi=null, renderscriptSupportModeEnabled=null, renderscriptSupportModeBlasEnabled=null, renderscriptNdkModeEnabled=null, versionCode=null, versionName=null, applicationId=null, testApplicationId=null, testInstrumentationRunner=null, testInstrumentationRunnerArguments={}, testHandleProfiling=null, testFunctionalTest=null, signingConfig=null, resConfig=null, mBuildConfigFields={}, mResValues={}, mProguardFiles=[], mConsumerProguardFiles=[], mManifestPlaceholders={}, mWearAppUnbundled=null} of type com.android.build.gradle.internal.dsl.ProductFlavor.
  </code></pre>
  <p>I was able to resolve the local error by adding the missing methods like so:</p>
  <pre><code>def appName = &quot;Engage&quot;;
  
  /**
   * Get the version name from command line param
   *
   * @return int If the param -PversionName is present then return int value or -1
   */
  def getAppName = { env -&gt;
    return (env ? appName + &quot; (&quot;+ env + &quot;)&quot; : appName);
  }
  
  /**
   * Get the version name from command line param
   *
   * @return int If the param -PversionName is present then return int value or -1
   */
  def getLauncher = { env -&gt;
      return (env ? &quot;engage-&quot; + env + &quot;.nfib.org&quot; : &quot;engage.nfib.org&quot;);
  }
  
  android {
      compileSdkVersion rootProject.ext.compileSdkVersion
  
      compileOptions {
          sourceCompatibility JavaVersion.VERSION_1_8
          targetCompatibility JavaVersion.VERSION_1_8
      }
  
      flavorDimensions &quot;default&quot;
  
      defaultConfig {
          applicationId &quot;com.nfib.engage&quot;
          minSdkVersion rootProject.ext.minSdkVersion
          targetSdkVersion rootProject.ext.targetSdkVersion
          versionCode 1
          versionName &quot;1.0&quot;
      }
      splits {
          abi {
              reset()
              enable enableSeparateBuildPerCPUArchitecture
              universalApk false  // If true, also generate a universal APK
              include &quot;armeabi-v7a&quot;, &quot;x86&quot;, &quot;arm64-v8a&quot;, &quot;x86_64&quot;
          }
      }
      signingConfigs {
          debug {
              storeFile file('debug.keystore')
              storePassword 'android'
              keyAlias 'androiddebugkey'
              keyPassword 'android'
          }
      }
      buildTypes {
          debug {
              signingConfig signingConfigs.debug
          }
          release {
              // Caution! In production, you need to generate your own keystore file.
              // see https://facebook.github.io/react-native/docs/signed-apk-android.
              signingConfig signingConfigs.debug
              minifyEnabled enableProguardInReleaseBuilds
              proguardFiles getDefaultProguardFile(&quot;proguard-android.txt&quot;), &quot;proguard-rules.pro&quot;
          }
      }
  
      productFlavors {
        dev {
          dimension 'default'
          resValue &quot;string&quot;, &quot;app_name&quot;, getAppName(&quot;INT&quot;)
          resValue &quot;string&quot;, &quot;link_launcher&quot;, getLauncher(&quot;dv&quot;)
          applicationIdSuffix &quot;.dv&quot;
          manifestPlaceholders = [onesignal_app_id: &quot;b78285eb-f1ec-46f3-9ad0-c7efe691a401&quot;,
                                  onesignal_google_project_number: &quot;584236827312&quot;]
        }
        qa {
          dimension 'default'
          resValue &quot;string&quot;, &quot;app_name&quot;, getAppName(&quot;QA&quot;)
          resValue &quot;string&quot;, &quot;link_launcher&quot;, getLauncher(&quot;qa&quot;)
          applicationIdSuffix &quot;.qa&quot;
          manifestPlaceholders = [onesignal_app_id: &quot;e4280f5e-62ec-41a4-bd86-f5b94e471a36&quot;,
                                  onesignal_google_project_number: &quot;162802054510&quot;]
        }
        ua {
          dimension 'default'
          resValue &quot;string&quot;, &quot;app_name&quot;, getAppName(&quot;UA&quot;)
          resValue &quot;string&quot;, &quot;link_launcher&quot;, getLauncher(&quot;ua&quot;)
          applicationIdSuffix &quot;.ua&quot;
          manifestPlaceholders = [onesignal_app_id: &quot;2ffd8dc0-9c6b-4035-999d-fc694194725a&quot;,
                                  onesignal_google_project_number: &quot;594905904045&quot;]
        }
        prod {
          dimension 'default'
          resValue &quot;string&quot;, &quot;app_name&quot;, getAppName()
          resValue &quot;string&quot;, &quot;link_launcher&quot;, getLauncher()
          manifestPlaceholders = [onesignal_app_id: &quot;82dcb42f-1d35-4b79-bc28-2d1d02dbda36&quot;,
                                  onesignal_google_project_number: &quot;601125149914&quot;]
        }
      }
  </code></pre>
  <p>Unfortunately, I continue to get the same error in Jenkins.</p>