Carthage: Getting error in Carthage Update

Created on 28 Feb 2017  Ā·  20Comments  Ā·  Source: Carthage/Carthage

  • carthage version: .20
  • xcodebuild -version: Xcode 8.2.1
  • Are you using --no-build? yes
  • Are you using --no-use-binaries? no
  • Are you using --use-submodules? no

Carthage Output
Since updating to .20 I am getting the following error on one of my dependencies:

Failed to write to /*****/Carthage/Checkouts/*****/Carthage/Checkouts/logger: Error Domain=NSCocoaErrorDomain Code=516 "The file ā€œloggerā€ couldn’t be saved in the folder ā€œCheckoutsā€ because a file with the same name already exists." UserInfo={NSFilePath=/****/Carthage/Checkouts/******/Carthage/Checkouts/logger, NSUnderlyingError=0x7fb6b2b7cfb0 {Error Domain=NSPOSIXErrorDomain Code=17 "File exists"}}

I have tried removing this Checkout directory but the error simply comes back again sometimes in a different framework.

bug

Most helpful comment

This is fixed in 0.20.1, which is out now and will hopefully be on Homebrew soon.

Sorry for the trouble everyone! We have added an integration test for this, so it shouldn't be an issue again.

All 20 comments

This may be related to #1715.

I am seeing the same issue. A clean bootstrap works fine, but subsequent bootstraps, even with --cache-builds are failing on the symlink file

Can you share a Cartfile that reproduces the issues? That will be a big help in fixing it.

I'm not sure it's the same problem, but it looks like it.
Cartfile

github "ikesyo/Himotoki" ~> 3.0
github "ishkawa/APIKit" ~> 3.0

```
$ carthage bootstrap --platform iOS
* No Cartfile.resolved found, updating dependencies
Fetching Himotoki
Fetching APIKit
Fetching Result
Checking out Himotoki at "3.0.1"
Downloading Result.framework binary at "3.1.0"
*
* Checking out APIKit at "3.1.2"
Failed to write to /private/tmp/test/Carthage/Checkouts/APIKit/Carthage/Checkouts/Result: Error Domain=NSCocoaErrorDomain Code=516 "The file ā€œResultā€ couldn’t be saved in the folder ā€œCheckoutsā€ because a file with the same name already exists." UserInfo={NSFilePath=/private/tmp/test/Carthage/Checkouts/APIKit/Carthage/Checkouts/Result, NSUnderlyingError=0x7f9a1b60e580 {Error Domain=NSPOSIXErrorDomain Code=17 "File exists"}}

Unfortunately I can not since it is all private repos. I can say that going back to 19.1 resolved the problem temporarily, i am looking into if there is a issue with that particular repo maybe / tags / dependencies.

We have a similar issue, also with private repos. We have a main app that pulls in some of our SDKs, that then have dependencies on other of our SDKS, one of which pulls in Alamofire. We end up with something like this in the output:

$ time carthage update  --platform iOS
*** Fetching HockeySDK-iOS
*** Fetching innotech-profile (dummy data)
*** Fetching fusion-sdk-ios
*** Fetching ios-snapshot-test-case
*** Fetching innotech-aaa (dummy)
*** Fetching libPhoneNumber-iOS
*** Fetching objective-c
*** Fetching Alamofire
*** Checking out Alamofire at "4.4.0"
*** Downloading HockeySDK-iOS.framework binary at "Version 4.1.3"
*** Checking out HockeySDK-iOS at "4.1.3"
*** Checking out ios-snapshot-test-case at "2.1.4"
*** Checking out libPhoneNumber-iOS at "0.8.17"
*** Checking out objective-c at "v4.5.12"
*** Checking out innotech-aaa at "12345678" (more dummy)
Failed to write to /Users/john/Coding/innotech-app/Carthage/Checkouts/innotech-aaa/Carthage/Checkouts/Alamofire: Error Domain=NSCocoaErrorDomain Code=516 "The file ā€œAlamofireā€ couldn’t be saved in the folder ā€œCheckoutsā€ because a file with the same name already exists." UserInfo={NSFilePath=/Users/john/Coding/innotech-app/Carthage/Checkouts/innotech-aaa/Carthage/Checkouts/Alamofire, NSUnderlyingError=0x7f9e04d66a90 {Error Domain=NSPOSIXErrorDomain Code=17 "File exists"}}

In our case the "innotech-aaa" dependency is reached by multiple paths so I don't know if that's adding to the problems? Something along the lines of:

App
|  \
S   P
|   | \
|   U  |
|   |  |
 \  |  /
   AAA

I'm unable to reproduce this with the Cartfile that @vincentisambart provided. šŸ˜ž

I'm seeing this error as well using PINRemoteImage. This Cartfile:

github "pinterest/PINRemoteImage" "master"

will reproduce the issue on version 0.20.0:

~/code/tmp/CarthageTest: carthage version
0.20.0
~/code/tmp/CarthageTest: cat Cartfile
github "pinterest/PINRemoteImage" "master"
~/code/tmp/CarthageTest: carthage bootstrap
*** Checking out libwebp at "v0.5.1"
*** Checking out PINOperation at "1.0.3"
*** Downloading PINCache.framework binary at "3.0.1 Beta 4"
*** Checking out PINRemoteImage at "a5ac670cac32ceebbd9b5d4aa6841dcef013bc70"
Failed to write to /Users/zach/code/tmp/CarthageTest/Carthage/Checkouts/PINRemoteImage/Carthage/Checkouts/libwebp: Error Domain=NSCocoaErrorDomain Code=516 "The file ā€œlibwebpā€ couldn’t be saved in the folder ā€œCheckoutsā€ because a file with the same name already exists." UserInfo={NSFilePath=/Users/zach/code/tmp/CarthageTest/Carthage/Checkouts/PINRemoteImage/Carthage/Checkouts/libwebp, NSUnderlyingError=0x7f83e5f5b5e0 {Error Domain=NSPOSIXErrorDomain Code=17 "File exists"}}
~/code/tmp/CarthageTest: 

Same issue here with different projects.

I'm doing my own research, but for now it occurs always with dependencies which has also their own dependencies managed through carthage:

Project -> Dependency A -> Dependency B

Way to reproduce:

~/tmp$ mkdir test
~/tmp$ cd test
~/tmp/test$ echo "github \"gigigoapps/gigigo-ios-passbook\" ~> 3.0" > Cartfile
~/tmp/test$ cat Cartfile
github "gigigoapps/gigigo-ios-passbook" ~> 3.0
~/tmp/test$ carthage update --no-use-binaries
*** Cloning gigigo-ios-passbook
*** Cloning gigigo-ios-lib
*** Checking out gigigo-ios-lib at "v2.2.7"
*** Checking out gigigo-ios-passbook at "v3.0"
*** xcodebuild output can be found in /var/folders/k2/w77m76fn0cv8q390cgd6rxcc0000gn/T/carthage-xcodebuild.yKYY37.log
*** Building scheme "GIGLibrary" in GIGLibrary.xcodeproj
*** Building scheme "GIGPassbook" in GIGPassbook.xcodeproj
~/tmp/test$ carthage update --no-use-binaries
*** Fetching gigigo-ios-passbook
*** Fetching gigigo-ios-lib
*** Checking out gigigo-ios-lib at "v2.2.7"
*** Checking out gigigo-ios-passbook at "v3.0"
Failed to write to /Users/alex/tmp/test/Carthage/Checkouts/gigigo-ios-passbook/Carthage/Checkouts/gigigo-ios-lib: Error Domain=NSCocoaErrorDomain Code=516 "The file ā€œgigigo-ios-libā€ couldn’t be saved in the folder ā€œCheckoutsā€ because a file with the same name already exists." UserInfo={NSFilePath=/Users/alex/tmp/test/Carthage/Checkouts/gigigo-ios-passbook/Carthage/Checkouts/gigigo-ios-lib, NSUnderlyingError=0x7fc695607830 {Error Domain=NSPOSIXErrorDomain Code=17 "File exists"}}
~/tmp/test$ carthage version
0.20.0

I hope this could be help

A number of oversights on my part concerning the git ls-tree call used to avoid conflicts in all the Carthage/Checkouts directories.

git ls-tree -r would list checked-in submodules, symlinks, the files inside recursed-through directories, but (problematically) not the directories themselves.

Instead, without recursion and with a trailing path separator, ls-tree lists just the directory contents, which is what should have been implemented to begin with:

 /// Git’s representation of file system objects at a path relative to the repository root.
+///
+/// - parameter path: Path separators at the end of `path` have significance of outputting directory contents.
+///                   Thankfully, multiple contiguous path separators seem to have no adverse effects.
+/// - note: Previously, `path` was recursed through — now, just iterated.
 internal func list(treeish: String, atPath path: String, inRepository repositoryURL: URL) -> SignalProducer<String, CarthageError> {
    return launchGitTask(
        // `ls-tree`, because `ls-files` returns no output (for all instances I’ve seen) on bare repos.
        // flag ā€œ-zā€ enables output separated by the nul character (`\0`).
-       [ "ls-tree", "-z", "-r", "--full-name", "--name-only", treeish, path ],
+       [ "ls-tree", "-z", "--full-name", "--name-only", treeish, path ],
        repositoryFileURL: repositoryURL

Using ls-tree more knowledgeably also eliminates path-resolving code (see below) containing another bug: /private-path standardization differing for existing file-system objects and non-existing URLs


Not important, but here’s what that fix would have been…

                    .flatMap(.merge) { (path: String) -> SignalProducer<String, CarthageError> in
+                       let directoryURL = self.directoryURL.standardizedFileURL
                        let componentsRelativeToDirectoryURL = {
-                           return URL(string: $0, relativeTo: self.directoryURL)?.standardizedFileURL.carthage_pathComponents
+                           return URL(string: $0, relativeTo: directoryURL)?.standardizedFileURL.carthage_pathComponents
                        }


Major apologies for introducing these errors. Along with a pull request, I’ll be writing loads more integration test — I'll try to incorporate as many of these as possible. Thanks for reproducing and submitting these, massively helpful!

Concerning the problem I reported, it seems that it doesn't occur if I pass --no-use-binaries to carthage. But if I remove the cache and do not pass --no-use-binaries it always occurs.

$ rm -rf ~/Library/Caches/org.carthage.CarthageKit # To be sure nothing strange might be in the cache
$ mkdir /tmp/xxxx # New empty directory
$ cd /tmp/xxxx
$ echo "github \"ikesyo/Himotoki\" ~> 3.0\ngithub \"ishkawa/APIKit\" ~> 3.0" > Cartfile
$ carthage bootstrap --platform iOS
*** No Cartfile.resolved found, updating dependencies
*** Cloning Himotoki
*** Cloning APIKit
*** Cloning Result
*** Checking out Himotoki at "3.0.1"
*** Downloading Result.framework binary at "3.1.0"
*** Checking out APIKit at "3.1.2"
Failed to write to /private/tmp/xxxx/Carthage/Checkouts/APIKit/Carthage/Checkouts/Result: Error Domain=NSCocoaErrorDomain Code=516 "The file ā€œResultā€ couldn’t be saved in the folder ā€œCheckoutsā€ because a file with the same name already exists." UserInfo={NSFilePath=/private/tmp/xxxx/Carthage/Checkouts/APIKit/Carthage/Checkouts/Result, NSUnderlyingError=0x7f819d14df70 {Error Domain=NSPOSIXErrorDomain Code=17 "File exists"}}

I can concur this is happening when the dependency is required by the parent project and some subproject as well.

I've the same issue as @grangej said.
Two of my frameworks ("Bluetooth" and "Service") depending on a "Base" framework. One further framework "AppUI" depends on the other three frameworks.
In the first run there is everything okay, but in the second run the error "Failed to write to ..." occurs. Deleting the shortcut folder "Base" in the checkout directory of Bluetooth and Service will solve the problem temporarily.

By the way, in two frameworks i used the relative path and in one framework the absolute path before. So Carthage tries to checkout und build the same framework twice. Maybe a check to the absolute path will be better on repos which are located local.

Is there a workaround for this? For now I'm just switching back to Carthage 0.18.1, the last version before 0.20.0 that I had previously built in Homebrew. (brew switch carthage 0.18.1).

If you're building from source you can patch in the changes from #1805 , otherwise rolling back to 0.19.1 is your best bet.

Note that the issue is that the checkout doesn't work because it already happened, so depending on when in the cycle the failure happened, you _may_ have proper checkouts, and be able to workaround it by running a subsequent carthage build to finish up. Wouldn't recommend for CI, but if you're just trying to get something built locally it could work.

Hello @geoffreywiseman!

Yes, there is 2 workarounds:

  1. Downgrade Carthage to v0.19.1, because current v0.20 is broken and the hotfix is not coming as quick as it should be.
  2. Remove the folder Carthage/Checkouts every time before run carthage bootstrap/update

There is a variation of workaround number 2: Remove only the conflictive symlinks (the path(s) that carthage says is failing)

I've written a small shell/bash script. Argument ($1) is the absolute path of the cartfile location, so it can be reused for all the different frameworks of my project.
This script removes the whole content of the checkouts folder, of the dependencies.

Example:
./script-name /path/to/cartfile

`#!/bin/bash

echo "remove all checkout folders of dependencies in $1"

if [[ "$1" = /* ]]; then
cd $1/Carthage/Checkouts;
for d in /; do
echo "removing checkouts of $d"
dirpath=$1'Carthage/Checkouts/'$d'Carthage/Checkouts//
'
rm -r $dirpath
done
else

&2 echo "no absolute path given"
fi`

Same issue with Realm.
Cartfile contains PF while whole chain is:

Realm -> PF -> App

This is fixed in 0.20.1, which is out now and will hopefully be on Homebrew soon.

Sorry for the trouble everyone! We have added an integration test for this, so it shouldn't be an issue again.

I can confirm that Carthage 0.20.1 is available on Homebrew and seems not to exhibit the same problem for me (as expected).

Was this page helpful?
0 / 5 - 0 ratings