When building, archiving, or uploading an app from Xcode, you may encounter an error or validation issue related to CFBundleShortVersionString.
Typical causes include a missing version, an invalid version format, a mismatch between Info.plist and Xcode build settings, or a difference between the version embedded in the archive and the version configured in App Store Connect.
CFBundleShortVersionString is the user-visible release version of the application. In Xcode, it normally appears as Version, while the corresponding build setting is MARKETING_VERSION.
For example:
Version = 2.3.1 Build = 42
normally corresponds to:
CFBundleShortVersionString = 2.3.1 CFBundleVersion = 42
The key to fixing these errors is to keep the release version separate from the build number and verify the version that is actually embedded in the final archive.
- What is CFBundleShortVersionString?
- CFBundleShortVersionString vs. CFBundleVersion
- Common situations where this error appears
- Common causes
- 1. The Version field is empty
- 2. MARKETING_VERSION is empty
- 3. The version contains a prefix or text
- 4. The version format is invalid
- 5. A build number is being used as the marketing version
- 6. Info.plist and MARKETING_VERSION disagree
- 7. Xcode generates Info.plist
- 8. Debug and Release use different versions
- 9. An .xcconfig file overrides the version
- 10. A user-defined variable expands incorrectly
- 11. CI does not provide the version variable
- 12. The App Store Connect version does not match
- 13. An app extension uses another version
- 14. The archive was not rebuilt after changing the version
- 15. The wrong archive is uploaded
- What to check first
- Solution 1: Use a valid release-version format
- Solution 2: Set MARKETING_VERSION
- Solution 3: Remove a leading v
- Solution 4: Do not add beta or release text to the version
- Solution 5: Keep Version and Build separate
- Solution 6: Correct CFBundleShortVersionString in a physical plist
- Solution 7: Reference MARKETING_VERSION from Info.plist
- Solution 8: If Xcode generates Info.plist, update Build Settings
- Solution 9: Check both Debug and Release
- Solution 10: Check the Archive configuration
- Solution 11: Search .xcconfig files
- Solution 12: Inspect resolved build settings
- Solution 13: Inspect a specific scheme
- Solution 14: Inspect Release directly
- Solution 15: Inspect the version inside the built app
- Solution 16: Match the App Store Connect version
- Solution 17: Update Version for a new release
- Solution 18: Keep Version the same and increment Build when appropriate
- Solution 19: Check bundled extensions
- Solution 20: Use a shared .xcconfig for several targets
- Solution 21: Verify CI version variables
- Solution 22: Fail CI when the version is empty
- Solution 23: Validate the version format in CI
- Solution 24: Update the marketing version with agvtool when configured
- Solution 25: Create a new archive after changing Version
- If Version changes do not appear in the archive
- If App Store Connect shows another version
- Should you use 1.0 or 1.0.0?
- What if you want a beta suffix?
- Example Version and Build workflow
- If CFBundleShortVersionString is missing from the source plist
- If the version cannot be changed from Build Settings
- Checking Version from the command line
- How to verify the version in an archive
- Will Clean Build Folder fix it?
- Should you delete DerivedData?
- What you should avoid
- Fast troubleshooting checklist
- Summary
What is CFBundleShortVersionString?
CFBundleShortVersionString identifies the release version of a bundle and is visible to users.
Apple’s current documentation defines the version in the form:
Major.Minor.Patch
For example:
1.0.0 2.3.1 10.14.1
In Xcode, this normally appears under:
Target → General → Identity → Version
The corresponding build setting is:
MARKETING_VERSION
CFBundleShortVersionString vs. CFBundleVersion
These keys have different purposes:
CFBundleShortVersionString: user-facing release versionCFBundleVersion: build identifier
For example:
Version 3.1.0 Build 127
corresponds to:
CFBundleShortVersionString = 3.1.0 CFBundleVersion = 127
Key point: You can keep the same release version while incrementing the build number for multiple binaries.
Common situations where this error appears
- The Version field is empty
- CFBundleShortVersionString is missing
- The version contains letters or unsupported symbols
- The version format is invalid
- MARKETING_VERSION is empty
- Info.plist and MARKETING_VERSION disagree
- A generated Info.plist is used but only a physical plist was edited
- Debug and Release have different versions
- Archive uses an old version
- An .xcconfig overrides MARKETING_VERSION
- The App Store Connect version does not match the archive
- An app extension has another version
- A CI version variable is empty
- An outdated archive is uploaded accidentally
Common causes
1. The Version field is empty
Open:
Target → General → Identity → Version
and verify that a release version is present.
2. MARKETING_VERSION is empty
Search Build Settings for:
MARKETING_VERSION
An empty value can result in a missing or invalid CFBundleShortVersionString.
3. The version contains a prefix or text
Avoid values such as:
v2.0.0 2.0.0 beta
Use a numeric dotted release version instead.
4. The version format is invalid
Use a three-component version:
2.1.3
representing major, minor, and patch revisions.
5. A build number is being used as the marketing version
A value such as:
CFBundleShortVersionString = 142
mixes the concepts of release version and build identifier.
A clearer configuration is:
CFBundleShortVersionString = 1.4.2 CFBundleVersion = 142
6. Info.plist and MARKETING_VERSION disagree
A physical plist may contain:
<key>CFBundleShortVersionString</key> <string>1.0.0</string>
while Build Settings contain:
MARKETING_VERSION = 2.0.0
7. Xcode generates Info.plist
Modern Xcode projects can use:
GENERATE_INFOPLIST_FILE = YES
When enabled, Xcode places the value of:
MARKETING_VERSION
into CFBundleShortVersionString in the generated Info.plist.
Editing an unrelated physical plist may therefore have no effect.
8. Debug and Release use different versions
Debug: MARKETING_VERSION = 2.0.0
Release:
MARKETING_VERSION = 1.9.0
This can make development builds appear correct while Archive uses the wrong version.
9. An .xcconfig file overrides the version
MARKETING_VERSION = 1.5.0
may override what you expect from the Xcode UI.
10. A user-defined variable expands incorrectly
MARKETING_VERSION = $(APP_VERSION)
If APP_VERSION is undefined, the final value may be empty.
11. CI does not provide the version variable
If the problem occurs only on CI, verify environment variables and configuration files used by that workflow.
12. The App Store Connect version does not match
The version embedded as CFBundleShortVersionString should match the version number configured for the release in App Store Connect.
13. An app extension uses another version
Widgets and other bundled extensions have their own target settings and should be included in troubleshooting.
14. The archive was not rebuilt after changing the version
Changing Version in Xcode does not modify archives that already exist.
15. The wrong archive is uploaded
If several archives are listed in Organizer, verify that you selected the newly created one.
What to check first
1. Check the Version field
Open:
Target → General → Identity → Version
For example:
2.3.1
2. Check MARKETING_VERSION
Search Build Settings for:
Marketing Version
The build-setting name is:
MARKETING_VERSION
3. Check Generate Info.plist File
Inspect:
GENERATE_INFOPLIST_FILE
If it is YES, troubleshoot MARKETING_VERSION and the generated plist configuration.
Important: Do not stop at the source plist. The most reliable check is the CFBundleShortVersionString inside the final archive.
Solution 1: Use a valid release-version format
Version = 1.0.0
or:
Version = 2.4.3
Solution 2: Set MARKETING_VERSION
MARKETING_VERSION = 2.3.1
Solution 3: Remove a leading v
Before:
v2.3.1
After:
2.3.1
Solution 4: Do not add beta or release text to the version
Before:
2.0.0-beta
After:
2.0.0
Use the build number to distinguish TestFlight builds.
Solution 5: Keep Version and Build separate
Version = 2.0.0 Build = 57
Solution 6: Correct CFBundleShortVersionString in a physical plist
<key>CFBundleShortVersionString</key> <string>2.3.1</string>
Solution 7: Reference MARKETING_VERSION from Info.plist
<key>CFBundleShortVersionString</key> <string>$(MARKETING_VERSION)</string>
This lets the build setting act as the central source for the release version.
Solution 8: If Xcode generates Info.plist, update Build Settings
GENERATE_INFOPLIST_FILE = YES MARKETING_VERSION = 2.3.1
Solution 9: Check both Debug and Release
Debug = 2.3.1 Release = 2.3.1
or use intentionally different values only if your release process genuinely requires them.
Solution 10: Check the Archive configuration
Open:
Product → Scheme → Edit Scheme → Archive
and identify which configuration is used.
Solution 11: Search .xcconfig files
grep -R "MARKETING_VERSION" .
Look for old or unexpected values.
Solution 12: Inspect resolved build settings
xcodebuild -showBuildSettings | grep MARKETING_VERSION
Solution 13: Inspect a specific scheme
xcodebuild \ -project MyApp.xcodeproj \ -scheme MyApp \ -showBuildSettings | grep MARKETING_VERSION
Solution 14: Inspect Release directly
xcodebuild \ -project MyApp.xcodeproj \ -scheme MyApp \ -configuration Release \ -showBuildSettings | grep MARKETING_VERSION
Solution 15: Inspect the version inside the built app
plutil -p /path/to/MyApp.app/Info.plist
To show only the release version:
plutil -p /path/to/MyApp.app/Info.plist | grep CFBundleShortVersionString
This is the value that actually reaches distribution.
Solution 16: Match the App Store Connect version
If App Store Connect defines the release as:
2.3.1
verify that the archive contains:
CFBundleShortVersionString = 2.3.1
Solution 17: Update Version for a new release
For example:
2.3.1 → 2.4.0
when preparing a new minor release.
Solution 18: Keep Version the same and increment Build when appropriate
For another binary of the same release:
Version = 2.3.1 Build = 41
can become:
Version = 2.3.1 Build = 42
Solution 19: Check bundled extensions
Inspect the marketing version of targets such as:
- Widget extensions
- Share extensions
- Notification service extensions
- Watch apps
Solution 20: Use a shared .xcconfig for several targets
MARKETING_VERSION = 2.3.1
This can reduce version drift between bundled targets.
Solution 21: Verify CI version variables
If you use:
MARKETING_VERSION = $(APP_VERSION)
check:
echo "$APP_VERSION"
Solution 22: Fail CI when the version is empty
if [ -z "$APP_VERSION" ]; then echo "APP_VERSION is empty" exit 1 fi
Solution 23: Validate the version format in CI
if ! echo "$APP_VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$'; then echo "Invalid APP_VERSION: $APP_VERSION" exit 1 fi
Adjust the check to match your release policy.
Solution 24: Update the marketing version with agvtool when configured
xcrun agvtool \ new-marketing-version 2.3.1
Note: agvtool depends on project versioning configuration. For many projects, changing Version directly in Xcode is simpler.
Solution 25: Create a new archive after changing Version
After updating the release version, create a fresh archive:
Product → Archive
Existing archives retain the version with which they were built.
If Version changes do not appear in the archive
Check:
- Whether you edited the correct target
- Whether MARKETING_VERSION is overridden
- The Release configuration
- .xcconfig values
- Environment variables
- Whether you created a fresh archive
- Whether Organizer is using the newest archive
If App Store Connect shows another version
Compare the release version in App Store Connect with the value in the archive.
For example:
App Store Connect: 2.4.0
Archive:
2.3.1
Update the appropriate side so they represent the same intended release.
Should you use 1.0 or 1.0.0?
Apple’s current CFBundleShortVersionString documentation specifies three period-separated integers representing major, minor, and patch revisions.
Using a consistent format such as:
1.0.0
avoids ambiguity and aligns with the documented format.
What if you want a beta suffix?
Instead of:
2.0.0-beta
keep:
2.0.0
as the release version and use different build numbers to distinguish TestFlight builds.
Example Version and Build workflow
During development of version 3.0.0:
Version 3.0.0 / Build 1 Version 3.0.0 / Build 2 Version 3.0.0 / Build 3 Version 3.0.0 / Build 4
A later patch release might use:
Version 3.0.1 / Build 5
If CFBundleShortVersionString is missing from the source plist
Check:
GENERATE_INFOPLIST_FILE
If it is YES, Xcode may generate the plist during the build.
In that case, inspect:
MARKETING_VERSION
instead of assuming a physical plist is required.
If the version cannot be changed from Build Settings
Switch Build Settings to:
Levels
and inspect whether MARKETING_VERSION comes from:
- Project settings
- Target settings
- .xcconfig
- Defaults
Checking Version from the command line
For a project:
xcodebuild \ -project MyApp.xcodeproj \ -scheme MyApp \ -showBuildSettings | grep -E "MARKETING_VERSION|GENERATE_INFOPLIST_FILE"
For a workspace:
xcodebuild \ -workspace MyApp.xcworkspace \ -scheme MyApp \ -showBuildSettings | grep -E "MARKETING_VERSION|GENERATE_INFOPLIST_FILE"
For Release:
xcodebuild \ -project MyApp.xcodeproj \ -scheme MyApp \ -configuration Release \ -showBuildSettings | grep -E "MARKETING_VERSION|GENERATE_INFOPLIST_FILE"
How to verify the version in an archive
plutil -p MyApp.app/Info.plist | grep CFBundleShortVersionString
This checks the version actually embedded in the binary you plan to upload.
Will Clean Build Folder fix it?
Not if MARKETING_VERSION or CFBundleShortVersionString is incorrect.
You can use:
Product → Clean Build Folder
after correcting configuration, but cleaning does not replace an invalid release version.
Should you delete DerivedData?
Usually not as the first step.
If you have already changed the configuration and suspect stale artifacts, you can try:
rm -rf ~/Library/Developer/Xcode/DerivedData/*
as a secondary troubleshooting action.
Note: Prioritize checking Release configuration and the actual CFBundleShortVersionString embedded in the archive before treating this as a cache problem.
What you should avoid
Do not add arbitrary text, dates, or labels to the release version merely to silence a validation error.
Avoid values such as:
2.0-final 2.0-beta version-2 2026.09.release
Keep CFBundleShortVersionString as a numeric dotted release version and use CFBundleVersion to distinguish individual builds.
Fast troubleshooting checklist
- Check Target → General → Identity → Version.
- Check MARKETING_VERSION.
- Use a Major.Minor.Patch version format.
- Remove prefixes and text such as v, beta, or release.
- Check GENERATE_INFOPLIST_FILE.
- If using a physical plist, inspect CFBundleShortVersionString.
- Compare Debug and Release.
- Check the Archive configuration.
- Check .xcconfig overrides.
- Check user-defined settings.
- Check CI environment variables.
- Check the version configured in App Store Connect.
- Check app-extension versions.
- Create a new archive after changing Version.
- Inspect CFBundleShortVersionString inside the archived app.
Summary
CFBundleShortVersionString errors in Xcode usually occur because the application’s release version is missing, invalid, or inconsistent between Xcode, Info.plist, the archive, and App Store Connect.
CFBundleShortVersionString is the user-facing release version. In Xcode it normally corresponds to the Version field and the MARKETING_VERSION build setting.
Apple’s current documentation defines the release version as three period-separated integers representing major, minor, and patch revisions.
When GENERATE_INFOPLIST_FILE is enabled, Xcode places MARKETING_VERSION into CFBundleShortVersionString in the generated Info.plist, so editing a separate source plist may not change the built application.
Start by checking Version, MARKETING_VERSION, and GENERATE_INFOPLIST_FILE.
If the issue appears only during Archive, check Release configuration. If it appears during upload, compare the archive’s CFBundleShortVersionString with the version configured in App Store Connect.
After changing Version, create a fresh archive and verify the CFBundleShortVersionString inside that archive. This is the most reliable way to confirm what will actually be distributed.
