I moved to the latest major Xcode. Then I ran a real build across the whole fleet — 46 apps.
Twenty failed to compile. Same error, same cause, every time.
error: invalid redeclaration of synthesized memberwise 'init(stringRepresentation:)'After a toolchain upgrade, how many of your apps do you actually build? Or do you open one and move on?
The cause was not my code
The error came from a paywall color type inside a payments SDK.
That struct's initializer lived in a private extension. So the compiler saw no initializer in the body and synthesized a memberwise one. Because the stored fields were optional, the synthesized initializer happened to match the name and argument shape of the one defined in the extension. Two declarations of the same thing.
Older compilers let it pass. The new one is stricter, and it surfaced.
And the SDK had already shipped a version that moved that initializer into the struct body. It was a pin bump. Twenty apps were blocked because I did not know that.
My first count was 16
When I first asked "how many are blocked," I searched for dependency lock files one level deep inside each app folder. I got 16.
Four more apps have a project layout one level deeper. The real number was 20. The count itself was an undercount.
find . -name Package.resolved -not -path '*/SourcePackages/*' -not -path '*/checkouts/*'For the boundary between broken and fixed SDK versions I did not trust release notes — I opened the tagged source.
git -C <SDK checkout> show <tag>:Sources/Paywalls/PaywallColor.swift \
| awk '/MARK: - Public constructors/{exit}1' \
| grep -c 'private init(stringRepresentation: String, underlyingColor'
# 1 = fixed version, 0 = broken versionHere is where it splits
Bump the pin locally in all 20 apps and they all build. Looks done.
Except that pin lives in Xcode's local workspace state file, and that file is .gitignored. Fixing it on this machine leaves no trace in the repo.
Would you commit all 20, or none?
Neither was right. Most apps declare the dependency loosely — "latest within the major version" — so a fresh clone picks up the fixed release and heals itself. The exception was two apps pinned more tightly, to "latest within the minor version." Those two stay broken on any machine that clones them.
Those two were the only fixes that had to land in the repo. Committing all 20 is noise; committing none means CI or the next clone breaks again.
The trap that inflates the failure count
Force-building a project that ships a watch app against a simulator destination produces a separate "no WatchKit" error. That is my own wrong destination, unrelated to this regression.
Count both in the same bucket and the failure number inflates — and the cause stops looking like one cause.
Self-check
- When you count dependency lock files, does your search reach nested project layouts?
- Do you decide by reading the pin, or by checking that a build artifact actually comes out? Reading the pin misses local workspace state entirely.
- How many of your fixes leave no trace in the repo?
The honest part
20 of 46 failed; 2 got a fix recorded in the repo. For the other 18, "fixed" really means "a fresh clone will heal itself" — and that remains my inference until someone actually clones and builds them.
Had I opened one app after the upgrade and moved on, the other 19 would have surfaced at release time.
Go build the app in your fleet that has gone unbuilt the longest.