Cannot submit to App Store with @zoom/meetingsdk-react-native version 6.4.10

I am getting the same issue reported in Unable to submit to App Store with latest Zoom SDK but with the React Native Meeting SDK on version 6.4.10:

Validation failed (409) This bundle is invalid. The value for key CFBundleShortVersionString ‘6.4.10.25465’ in the Info.plist file at ‘Payload/PomeloCare.app/Frameworks/MobileRTC.framework’ must be a period-separated list of at most three non-negative integers.

This is blocking submission of our app. If this is fixed in a new version of the SDK, can you release it to npm?

1 Like

You’re hitting this because Apple only allows up to 3 digits in CFBundleShortVersionString. Zoom pushed 6.4.10.25465, which fails validation. The workaround is to manually edit the framework’s Info.plist and change it to 6.4.10 before submitting, or wait for Zoom’s next SDK patch that fixes this.

1 Like

For posterity - if any Expo users are out there that encounter this, I added an EAS post-install script:

#!/bin/bash

# eas-hooks/post-install.sh

echo "Fixing Zoom SDK CFBundleShortVersionString for App Store compliance..."

# Function to update plist version value to fix invalid verson string.
update_plist() {
    local plist_path="$1"
    /usr/libexec/PlistBuddy -c "Set :CFBundleVersion 6.4.10" "$plist_path"
    /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString 6.4.10" "$plist_path"
    echo "Updated: $plist_path"
}

if [[ "$EAS_BUILD_PLATFORM" == "android" ]]; then
  echo "Zoom SDK version fix not needed for Android builds"
elif [[ "$EAS_BUILD_PLATFORM" == "ios" ]]; then
  echo "Searching for any MobileRTC.framework locations..."
  find . -name "Info.plist" -path "*/MobileRTC.framework/*" 2>/dev/null | while read plist; do
    echo "Found: $plist"
    update_plist "$plist"
  done
fi

echo "Zoom SDK version fix completed."

Which you can hook up by adding the following to your package.json:

{
  // ...
  "scripts": {
    //...
    "eas-build-post-install": "./eas-hooks/post-install.sh"
  },
}

Docs: Build lifecycle hooks - Expo Documentation

Definitely an insane hack! Would love it if the Zoom team could publish a new NPM version for this SDK. We found that we had to upgrade from 6.2.10 because it was not working on React Native’s new architecture.

Hi, any update on this issue?

If you are using react native CLI.

 post_install do |installer|

    react_native_post_install(

      installer,

      config[:reactNativePath],

:mac_catalyst_enabled => false,

:ccache_enabled => ccache_enabled?(podfile_properties),

)



# --- Zoom SDK CFBundleShortVersionString Fix ---

puts "🔍 Starting Zoom SDK version fix..."



# Find all MobileRTC.framework Info.plist files

zoom_sdk_path = File.join(installer.sandbox.root, 'ZoomMeetingSDK')

puts "🔍 Looking in: #{zoom_sdk_path}"



Dir.glob(File.join(zoom_sdk_path, '**/MobileRTC.framework/Info.plist')).each do |plist_path|

puts "🧩 Fixing Zoom SDK Info.plist at: #{plist_path}"

begin

# Use plutil to convert to XML, modify, and convert back

system("plutil -convert xml1 '#{plist_path}'")



# Read the plist file

plist_content = File.read(plist_path)



# Replace the version strings using regex

plist_content = plist_content.gsub(/<key>CFBundleVersion<\/key>\s*<string>[^<]*<\/string>/, '<key>CFBundleVersion</key><string>6.4.10</string>')

plist_content = plist_content.gsub(/<key>CFBundleShortVersionString<\/key>\s*<string>[^<]*<\/string>/, '<key>CFBundleShortVersionString</key><string>6.4.10</string>')



# Write the modified content back

File.open(plist_path, 'w') { |f| f.write(plist_content) }



# Convert back to binary format

system("plutil -convert binary1 '#{plist_path}'")



puts "✅ Patched: #{plist_path}"

rescue => e

puts "⚠️ Error patching #{plist_path}: #{e}"

end

end

puts "🏁 Finished Zoom SDK version fix"

# --- End Zoom SDK Fix ---

add above change in podFile to fix this issue.

If you are using Expo.

withZoomSDKVersionFix.js

const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
const { withDangerousMod } = require('@expo/config-plugins');

const TARGET_VERSION = '6.4.10';

/**
 * Zoom SDK version fix code to be injected into Podfile
 */
const ZOOM_SDK_FIX_CODE = `
    # --- Zoom SDK CFBundleShortVersionString Fix ---
    puts "🔍 Starting Zoom SDK version fix..."

    # Find all MobileRTC.framework Info.plist files
    zoom_sdk_path = File.join(installer.sandbox.root, 'ZoomMeetingSDK')
    puts "🔍 Looking in: #{zoom_sdk_path}"

    Dir.glob(File.join(zoom_sdk_path, '**/MobileRTC.framework/Info.plist')).each do |plist_path|
      puts "🧩 Fixing Zoom SDK Info.plist at: #{plist_path}"
      begin
        # Use plutil to convert to XML, modify, and convert back
        system("plutil -convert xml1 '#{plist_path}'")

        # Read the plist file
        plist_content = File.read(plist_path)

        # Replace the version strings using regex
        plist_content = plist_content.gsub(/<key>CFBundleVersion<\\/key>\\s*<string>[^<]*<\\/string>/, '<key>CFBundleVersion</key><string>6.4.10</string>')
        plist_content = plist_content.gsub(/<key>CFBundleShortVersionString<\\/key>\\s*<string>[^<]*<\\/string>/, '<key>CFBundleShortVersionString</key><string>6.4.10</string>')

        # Write the modified content back
        File.open(plist_path, 'w') { |f| f.write(plist_content) }

        # Convert back to binary format
        system("plutil -convert binary1 '#{plist_path}'")

        puts "✅ Patched: #{plist_path}"
      rescue => e
        puts "⚠️ Error patching #{plist_path}: #{e}"
      end
    end
    puts "🏁 Finished Zoom SDK version fix"
    # --- End Zoom SDK Fix ---`;

/**
 * Inject Zoom SDK fix code into Podfile
 */
function injectZoomFixIntoPodfile(podfilePath) {
  try {
    if (!fs.existsSync(podfilePath)) {
      console.log('⚠️ Podfile not found, skipping Zoom SDK fix injection');
      return;
    }

    let podfileContent = fs.readFileSync(podfilePath, 'utf8');

    // Check if Zoom SDK fix is already present
    if (podfileContent.includes('Zoom SDK CFBundleShortVersionString Fix')) {
      console.log('✅ Zoom SDK fix already present in Podfile');
      return;
    }

    // Find the post_install block and inject the code before the final 'end' of the post_install block
    // Look for the pattern: post_install do |installer| ... end (but not nested ends)
    const lines = podfileContent.split('\n');
    let postInstallStart = -1;
    let postInstallEnd = -1;
    let braceLevel = 0;
    let inPostInstall = false;

    for (let i = 0; i < lines.length; i++) {
      const line = lines[i];

      if (line.includes('post_install do |installer|')) {
        postInstallStart = i;
        inPostInstall = true;
        braceLevel = 0;
        continue;
      }

      if (inPostInstall) {
        // Count opening and closing braces/blocks
        if (line.includes(' do ') || line.includes('{')) {
          braceLevel++;
        }
        if (line.trim() === 'end' && braceLevel === 0) {
          postInstallEnd = i;
          break;
        }
        if (line.trim() === 'end') {
          braceLevel--;
        }
      }
    }

    if (postInstallStart !== -1 && postInstallEnd !== -1) {
      // Insert the Zoom SDK fix code before the final 'end' of post_install
      lines.splice(postInstallEnd, 0, ZOOM_SDK_FIX_CODE);

      const updatedContent = lines.join('\n');
      fs.writeFileSync(podfilePath, updatedContent, 'utf8');
      console.log('✅ Successfully injected Zoom SDK fix into Podfile');
    } else {
      console.log('⚠️ Could not find proper post_install block in Podfile');
    }
  } catch (err) {
    console.warn(`⚠️ Failed to inject Zoom SDK fix into Podfile: ${err.message}`);
  }
}

const withZoomSDKVersionFix = (config) => {
  // Inject Zoom SDK fix code into Podfile during prebuild
  config = withDangerousMod(config, [
    'ios',
    (config) => {
      const iosRoot = path.join(config.modRequest.projectRoot, 'ios');
      const podfilePath = path.join(iosRoot, 'Podfile');

      console.log('🔧 Injecting Zoom SDK fix into Podfile...');
      injectZoomFixIntoPodfile(podfilePath);

      return config;
    },
  ]);

  return config;
};

module.exports = withZoomSDKVersionFix;

In your app.config.js:

export default {
  name: "App",
  slug: "app",
  version: "1.0.0",
  plugins: ["./plugins/withZoomPodfileFix"],
};