information

How to Fix CFBundleVersion Errors in Xcode

When building, archiving, or uploading an app from Xcode, you may encounter an error or validation message related to CFBundleVersion.

Examples include:

CFBundleVersion is missing

or validation errors indicating that the bundle version has an invalid format or cannot be accepted for the uploaded build.

CFBundleVersion identifies a particular build of your app. In Xcode, it normally corresponds to the value shown as Build, and the associated build setting is CURRENT_PROJECT_VERSION.

The key to fixing these errors is to separate the user-facing version from the build number, determine whether the target uses a generated or physical Info.plist, and verify the final CFBundleVersion that is actually placed in the built app.

  1. What is CFBundleVersion?
  2. CFBundleVersion vs. CFBundleShortVersionString
  3. Common situations where CFBundleVersion errors occur
  4. Common causes
    1. 1. The Build field is empty
    2. 2. CURRENT_PROJECT_VERSION is empty
    3. 3. The build number contains arbitrary text
    4. 4. Whitespace is present
    5. 5. Info.plist and Build Settings disagree
    6. 6. Xcode generates Info.plist automatically
    7. 7. Debug and Release have different values
    8. 8. An .xcconfig file overrides the build number
    9. 9. A user-defined build variable is empty
    10. 10. CI does not provide the build number
    11. 11. An automatic increment script failed
    12. 12. Apple Generic Versioning is not fully configured
    13. 13. An app extension has another build number
    14. 14. Multiple targets are updated independently
    15. 15. The same uploaded build is reused
  5. What to check first
    1. 1. Check the Build field in Xcode
    2. 2. Check Current Project Version
    3. 3. Check Generate Info.plist File
  6. Solution 1: Set a build number
  7. Solution 2: Set CURRENT_PROJECT_VERSION
  8. Solution 3: Check CFBundleVersion in a physical Info.plist
  9. Solution 4: Use a valid numeric build identifier
  10. Solution 5: Keep Version and Build separate
  11. Solution 6: If Xcode generates Info.plist, fix the build setting
  12. Solution 7: Check both Debug and Release
  13. Solution 8: Check the Archive configuration
  14. Solution 9: Fix .xcconfig overrides
  15. Solution 10: Inspect resolved build settings
  16. Solution 11: Check the Release value directly
  17. Solution 12: Inspect the processed Info.plist
  18. Solution 13: Use plutil to inspect plist values
  19. Solution 14: Increment the build number
  20. Solution 15: Use agvtool when your project uses Apple Generic Versioning
  21. Solution 16: Check CI build-number variables
  22. Solution 17: Fail early when the build number is missing
  23. Solution 18: Check every bundled target
  24. Solution 19: Update extension build numbers too
  25. Solution 20: Use a shared .xcconfig for multiple targets
  26. Solution 21: Avoid unnecessary direct plist rewriting in build scripts
  27. Solution 22: Reference CURRENT_PROJECT_VERSION from a physical plist
  28. Solution 23: Inspect build-setting precedence
  29. Solution 24: Check user-defined variable names
  30. Solution 25: Inspect the build log
  31. When uploading to App Store Connect
  32. Should CFBundleVersion increase for every uploaded build?
  33. Can the app version stay the same while only the build changes?
  34. If changing Build does not affect the archive
  35. How to verify the build number in an archive
  36. If you cannot find CFBundleVersion in a source Info.plist
  37. If CFBundleVersion appears correct but the error remains
  38. Will Clean Build Folder fix it?
  39. Should you delete DerivedData?
  40. What you should avoid
  41. Fast troubleshooting checklist
  42. Summary

What is CFBundleVersion?

CFBundleVersion identifies a particular build of a bundle.

In Xcode, it normally appears under:

Target → General → Identity → Build

The corresponding build setting is:

CURRENT_PROJECT_VERSION

For example:

Version: 1.2.0 Build: 35

typically corresponds to:

CFBundleShortVersionString = 1.2.0 CFBundleVersion = 35

Key point: CFBundleVersion is the build identifier. CFBundleShortVersionString is the user-facing app version. They serve different purposes.

CFBundleVersion vs. CFBundleShortVersionString

These two keys are easy to confuse.

  • CFBundleVersion: identifies the build
  • CFBundleShortVersionString: identifies the user-facing release version

For example:

Version 2.1.0 Build 147

means:

CFBundleShortVersionString = 2.1.0 CFBundleVersion = 147

Common situations where CFBundleVersion errors occur

  • The Build field is empty
  • CFBundleVersion is missing
  • The build value contains unsupported text or symbols
  • The build value contains whitespace
  • Info.plist and Build Settings disagree
  • A generated Info.plist is used but only the source plist was edited
  • Debug and Release use different build numbers
  • Archive uses an outdated Release value
  • An .xcconfig file overrides CURRENT_PROJECT_VERSION
  • Different targets have inconsistent build settings
  • An app extension has a mismatched bundle version
  • A CI build-number script fails
  • An environment variable expands to an empty value
  • An already-used build identifier is uploaded again

Common causes

1. The Build field is empty

Open:

Target → General → Identity → Build

and make sure it contains a valid build value.

2. CURRENT_PROJECT_VERSION is empty

Search Build Settings for:

CURRENT_PROJECT_VERSION

An empty value can result in a missing or invalid CFBundleVersion.

3. The build number contains arbitrary text

A value such as:

build35

or:

release-35

should be replaced with a suitable numeric build identifier.

4. Whitespace is present

35 beta

is not a good build-number value.

5. Info.plist and Build Settings disagree

A physical plist may contain:

<key>CFBundleVersion</key> <string>20</string>

while another build setting or configuration supplies a different value.

6. Xcode generates Info.plist automatically

Modern Xcode projects can use:

GENERATE_INFOPLIST_FILE = YES

When this setting is enabled, CURRENT_PROJECT_VERSION is used to populate CFBundleVersion in the generated plist.

Editing an unrelated physical plist may therefore have no effect.

7. Debug and Release have different values

For example:

Debug: CURRENT_PROJECT_VERSION = 35

Release:
CURRENT_PROJECT_VERSION =

This can allow ordinary development builds to work while Archive fails.

8. An .xcconfig file overrides the build number

CURRENT_PROJECT_VERSION = 20

may override the value you expected from the Xcode UI.

9. A user-defined build variable is empty

CURRENT_PROJECT_VERSION = $(BUILD_NUMBER)

If BUILD_NUMBER is undefined, the resolved build value may be empty.

10. CI does not provide the build number

A build-number environment variable may exist locally or in one workflow but be missing in another.

11. An automatic increment script failed

A pre-build or CI script may leave an old or empty value if it terminates early.

12. Apple Generic Versioning is not fully configured

If you use agvtool, confirm that the project’s versioning configuration supports it and that CURRENT_PROJECT_VERSION is set.

13. An app extension has another build number

Widgets and other extensions have their own target settings and should be included in your troubleshooting.

14. Multiple targets are updated independently

Changing only the main app target can leave other bundled targets on outdated values.

15. The same uploaded build is reused

When uploading a new binary, increment the build identifier so the new build can be distinguished from previously uploaded builds.

What to check first

1. Check the Build field in Xcode

Open:

Target → General → Identity

and inspect:

Version Build

For example:

Version = 1.0 Build = 35

2. Check Current Project Version

Search Build Settings for:

Current Project Version

The underlying key is:

CURRENT_PROJECT_VERSION

3. Check Generate Info.plist File

Inspect:

GENERATE_INFOPLIST_FILE

If it is YES, troubleshoot the generated plist configuration rather than assuming a physical Info.plist is the single source of truth.

Important: When Xcode generates Info.plist, CURRENT_PROJECT_VERSION is the important setting for the generated CFBundleVersion.

Solution 1: Set a build number

Open:

Target → General → Identity → Build

and enter a value such as:

35

Solution 2: Set CURRENT_PROJECT_VERSION

CURRENT_PROJECT_VERSION = 35

Solution 3: Check CFBundleVersion in a physical Info.plist

If your project uses a physical plist:

<key>CFBundleVersion</key> <string>35</string>

A common configuration instead references the build setting:

<key>CFBundleVersion</key> <string>$(CURRENT_PROJECT_VERSION)</string>

In that case, update CURRENT_PROJECT_VERSION rather than hard-coding the plist.

Solution 4: Use a valid numeric build identifier

Replace:

Build = beta-35

with something like:

Build = 35

Solution 5: Keep Version and Build separate

A clean configuration might be:

Version = 2.3.0 Build = 147

Solution 6: If Xcode generates Info.plist, fix the build setting

GENERATE_INFOPLIST_FILE = YES CURRENT_PROJECT_VERSION = 35

Xcode then places the build value into the generated CFBundleVersion.

Solution 7: Check both Debug and Release

Verify that every configuration resolves to the intended value.

Debug = 35 Release = 35

Solution 8: Check the Archive configuration

Open:

Product → Scheme → Edit Scheme → Archive

Then inspect CURRENT_PROJECT_VERSION for the configuration used by Archive.

Solution 9: Fix .xcconfig overrides

CURRENT_PROJECT_VERSION = 35

You can search the project with:

grep -R "CURRENT_PROJECT_VERSION" .

Solution 10: Inspect resolved build settings

xcodebuild -showBuildSettings | grep CURRENT_PROJECT_VERSION

For a specific project and scheme:

xcodebuild \ -project MyApp.xcodeproj \ -scheme MyApp \ -showBuildSettings | grep CURRENT_PROJECT_VERSION

Solution 11: Check the Release value directly

xcodebuild \ -project MyApp.xcodeproj \ -scheme MyApp \ -configuration Release \ -showBuildSettings | grep CURRENT_PROJECT_VERSION

Solution 12: Inspect the processed Info.plist

After building or archiving, check the plist inside the actual app bundle:

plutil -p /path/to/MyApp.app/Info.plist

To focus on the build number:

plutil -p /path/to/MyApp.app/Info.plist | grep CFBundleVersion

This shows the value that was actually embedded in the build.

Solution 13: Use plutil to inspect plist values

plutil -p Info.plist

is a useful way to inspect the effective key/value contents of a plist file.

Solution 14: Increment the build number

If the previous build was:

35

use:

36

for the next uploaded binary when appropriate.

Solution 15: Use agvtool when your project uses Apple Generic Versioning

xcrun agvtool new-version -all 36

Check the current version with:

xcrun agvtool what-version

Note: agvtool requires compatible project versioning settings. For a simple project, updating the Build field directly may be easier.

Solution 16: Check CI build-number variables

If you use:

CURRENT_PROJECT_VERSION = $(CI_BUILD_NUMBER)

verify that CI_BUILD_NUMBER exists:

echo "$CI_BUILD_NUMBER"

Solution 17: Fail early when the build number is missing

if [ -z "$CI_BUILD_NUMBER" ]; then echo "CI_BUILD_NUMBER is empty" exit 1 fi

This prevents a later plist or upload failure with a less useful error message.

Solution 18: Check every bundled target

For projects containing:

MyApp MyWidget NotificationService

inspect CURRENT_PROJECT_VERSION for each target.

Solution 19: Update extension build numbers too

If the main app and its bundled extensions are intended to share a build identifier, update them together.

Solution 20: Use a shared .xcconfig for multiple targets

CURRENT_PROJECT_VERSION = 36

A shared setting can reduce accidental mismatches between the app and its extensions.

Solution 21: Avoid unnecessary direct plist rewriting in build scripts

Scripts that directly modify the built Info.plist can conflict with Xcode’s own plist generation and processing.

Where possible, keep the build identifier in:

CURRENT_PROJECT_VERSION

and let the normal build process propagate it.

Solution 22: Reference CURRENT_PROJECT_VERSION from a physical plist

<key>CFBundleVersion</key> <string>$(CURRENT_PROJECT_VERSION)</string>

This makes the build setting the central source for the build identifier.

Solution 23: Inspect build-setting precedence

Use the Levels view in Xcode Build Settings to identify whether the final value comes from:

  • Default settings
  • Project settings
  • Target settings
  • .xcconfig

Solution 24: Check user-defined variable names

A typo such as:

BUILD_NUM

instead of:

BUILD_NUMBER

can result in an empty expansion.

Solution 25: Inspect the build log

Open the failed build in Xcode’s Report navigator and search for:

ProcessInfoPlistFile

and:

CFBundleVersion

This can help reveal the final value and the build phase where the problem occurs.

When uploading to App Store Connect

You can upload multiple builds for the same app version as long as each new binary has an appropriate distinct build identifier.

For example:

Version 1.2.0 Build 40

Version 1.2.0
Build 41

Version 1.2.0
Build 42

Incrementing the build number for each new uploaded binary is a straightforward way to keep builds distinct.

Should CFBundleVersion increase for every uploaded build?

For a new binary submitted for the same app version, use a new build identifier rather than reusing the previous uploaded build.

A simple sequence works well:

100 101 102 103

Can the app version stay the same while only the build changes?

Yes.

For example:

Version 2.0.0 Build 1

can be followed by:

Version 2.0.0 Build 2

for another binary of the same release version.

If changing Build does not affect the archive

Check:

  • Whether you edited the correct target
  • The Archive build configuration
  • Whether CURRENT_PROJECT_VERSION is overridden
  • Whether an .xcconfig still supplies an old value
  • Whether an extension uses another value
  • Whether you created a new archive after the change
  • Whether you are accidentally uploading an older archive

How to verify the build number in an archive

Inspect the Info.plist inside the archived app bundle:

plutil -p MyApp.app/Info.plist | grep CFBundleVersion

This verifies the build identifier that will actually be uploaded.

If you cannot find CFBundleVersion in a source Info.plist

This can be normal when:

GENERATE_INFOPLIST_FILE = YES

is enabled.

Check:

Target → General → Identity → Build

or:

Build Settings → Current Project Version

Note: A project does not need a visible source Info.plist for CFBundleVersion to exist. Xcode can generate the plist during the build.

If CFBundleVersion appears correct but the error remains

Check:

  • The Release configuration
  • App extension values
  • .xcconfig overrides
  • User-defined build variables
  • CI environment variables
  • The processed Info.plist inside the final app
  • Whether the archive being uploaded is actually the newest one

Will Clean Build Folder fix it?

Not if the build identifier itself is missing or invalid.

You may use:

Product → Clean Build Folder

after changing build settings if you suspect stale artifacts, but the configuration still needs to be correct.

Should you delete DerivedData?

Usually not as the first fix.

You can try:

rm -rf ~/Library/Developer/Xcode/DerivedData/*

as a secondary step, but it cannot repair an empty or invalid CURRENT_PROJECT_VERSION.

Note: Check the Build field, CURRENT_PROJECT_VERSION, Release configuration, and bundled extensions before treating this as a cache problem.

What you should avoid

Do not replace CFBundleVersion with arbitrary text simply to silence a validation error.

Avoid values such as:

build-final release test-build

Use a build identifier that is valid and easy to increment.

Also remember to check bundled extensions instead of updating only the main application target.

Fast troubleshooting checklist

  1. Check General → Identity → Build.
  2. Check CURRENT_PROJECT_VERSION.
  3. Check GENERATE_INFOPLIST_FILE.
  4. If using a physical plist, check CFBundleVersion.
  5. Remove unsupported text and whitespace from the build identifier.
  6. Compare Debug and Release.
  7. Check the Archive configuration.
  8. Check .xcconfig overrides.
  9. Check user-defined variables.
  10. Check CI build-number variables.
  11. Check app-extension build settings.
  12. Check every bundled target.
  13. Use xcodebuild -showBuildSettings to inspect the resolved value.
  14. Inspect the processed Info.plist in the archive.
  15. Increment the build identifier before uploading a new binary when necessary.

Summary

CFBundleVersion errors in Xcode are usually caused by a missing, invalid, stale, or inconsistent build identifier.

CFBundleVersion identifies the app build. In Xcode, it normally corresponds to the Build field and the CURRENT_PROJECT_VERSION build setting.

For targets that use generated Info.plist files, CURRENT_PROJECT_VERSION supplies the CFBundleVersion value during the build, so editing a physical plist may not be relevant.

Start by checking the target’s Build field, CURRENT_PROJECT_VERSION, and GENERATE_INFOPLIST_FILE.

If Archive alone fails, inspect the Release configuration. If CI alone fails, inspect environment variables and .xcconfig files. If your app includes extensions, check their build settings as well.

For upload problems, verify the CFBundleVersion in the actual archived app and use a new build identifier for a new binary when appropriate.

Cleaning the build folder or deleting DerivedData is secondary. The essential fix is to make sure the build identifier embedded in the final bundle is valid and matches the build you intend to distribute.