Description
[REQUIRED] Please fill in the following fields:
- Pre-built SDK from the website or open-source from this repo: Pre-built SDK from website
- Firebase C++ SDK version: 12.7.0
- Problematic Firebase Component: Storage
- Other Firebase Components in use: Auth, Firestore, Functions, Analytics, Messaging, Remote Config
- Platform you are using the C++ SDK on: macOS
- Platform you are targeting: iOS
❗️[iOS][Storage] GetFile() download fails with NSCocoaErrorDomain Code=262 on valid file path
Calling StorageReference::GetFile()
on iOS fails consistently when attempting to download to a valid sandboxed absolute path. This does not happen on Android or Windows using the same C++ code and Firebase bucket, suggesting the problem lies in the iOS native layer of the C++ SDK.
📄 Error Log Example
Could not remove previous file at /private/var/mobile/Containers/Data/Application/1AADB80E-8E59-4531-83DF-FD292F7BD24C/tmp/CFNetworkDownload_6CZmV6.tmp due to Error Domain=NSCocoaErrorDomain Code=262 "The specified URL type isn’t supported for opening the file." UserInfo={NSFilePath=/var/mobile/Containers/Data/Application/1AADB80E-8E59-4531-83DF-FD292F7BD24C/Documents/patch/asset/100000_100001.zip, NSURL=/var/mobile/Containers/Data/Application/1AADB80E-8E59-4531-83DF-FD292F7BD24C/Documents/patch/asset/100000_100001.zip}
🔍 Relevant Code Snippet (C++ - Firebase Storage Download)
auto app = firebase::App::GetInstance();
if (app == nullptr) return false;
auto storage = firebase::storage::Storage::GetInstance(app);
if (storage == nullptr) return false;
auto storage_ref = storage->GetReference(file_path);
firebase::storage::Controller controller;
auto download_task = storage_ref.GetFile(local_path.c_str(), g_storageListener, &controller);
download_task.OnCompletion([local_path, outputPath](const firebase::Future<size_t>& result) {
Director::getInstance()->getScheduler()->performFunctionInCocosThread([local_path, outputPath, result]() {
if (result.status() == firebase::kFutureStatusComplete) {
if (result.error() == firebase::storage::kErrorNone) {
auto strExt = cocos2d::FileUtils::getInstance()->getFileExtension(local_path);
bool bIsZip = strExt == ".zip" || strExt == "zip";
if (g_storageListener) g_storageListener->onSuccessDownload(bIsZip);
if (bIsZip) unzipAsync(local_path, outputPath);
} else {
if (g_storageListener) g_storageListener->onFailed(result.error(), result.error_message());
}
} else {
if (g_storageListener) g_storageListener->onFailed(result.error(), result.error_message());
}
});
});
💡 Root Cause Hypothesis
In the iOS bridge layer (storage_ios.mm
), the SDK likely uses:
NSURL* url = [NSURL URLWithString:destinationPath]; // ❌ returns nil for file paths
This should instead use:
NSURL* url = [NSURL fileURLWithPath:destinationPath]; // ✅ correct for local files
NSURL(string:)
is not valid for absolute file paths and returns nil
, leading to NSCocoaErrorDomain Code=262
.
✅ Confirmed Conditions
- The destination directory exists
- The file does not exist beforehand
- File system is writable
- Same logic works fine on Android and Windows
- Issue occurs in both Firebase C++ SDK 12.7.0 and 12.8.0
🧪 Reproduction Steps
- On iOS, download a file using
StorageReference::GetFile()
with an absolute path - Ensure the destination directory exists and the file doesn't
- Observe that the download fails and logs NSCocoaErrorDomain 262
🔗 Related to But Not Fixed by PR #1570
- That PR fixed an async crash on iOS caused by pointer misuse
- This issue is unrelated, caused by invalid
NSURL
usage for absolute paths - Still present in current iOS SDK 11.14.0 (SPM/CocoaPods)
✅ Expected Behavior
GetFile()
should succeed if destination path is valid- SDK should never use
NSURL(string:)
for absolute paths
Suggested Fix
Update internal SDK code to use [NSURL fileURLWithPath:]
for any local destination string.
Workaround
Append a random suffix (e.g., UUID) to the filename to avoid SDK's internal delete logic. However, this is not robust for production.
📦 Dependency Versions
- Firebase C++ SDK: 12.7.0 / 12.8.0
- Firebase iOS SDK: 11.14.0
From SwiftPM:
Firebase 11.14.0
FirebaseStorage 11.14.0
AppCheck 11.2.0
GoogleAppMeasurement 11.14.0
GoogleUtilities 8.1.0
GoogleDataTransport 10.1.0
GoogleSignIn 8.0.0
GTMAppAuth 4.1.1
GTMSessionFetcher 3.5.0
nanopb 2.30910.0
gRPC 1.69.0
abseil 1.2024072200.0
Promises 2.4.0
SwiftProtobuf 1.28.2
Thank you for reviewing this iOS-specific regression.