After moving a SwiftUI project to Xcode 27, a property that combines @State with another property wrapper can fail with invalid redeclaration of synthesized property '_x'. In Xcode 27, @State is a Swift macro rather than a property wrapper. The macro and the additional wrapper both try to synthesize backing storage with the same underscore-prefixed name. This guide explains the cause and the safe migration recommended by Apple’s TN3211.
The error message
error: invalid redeclaration of synthesized property '_counter'
Apple’s diagnostic reference uses the generic property name:
invalid redeclaration of synthesized property '_x'
Example that triggers the error
import SwiftUI
@propertyWrapper
struct Clamped {
private var value: Int
private let range: ClosedRange<Int>
var wrappedValue: Int {
get { value }
set { value = min(max(newValue, range.lowerBound), range.upperBound) }
}
init(wrappedValue: Int, _ range: ClosedRange<Int>) {
self.range = range
self.value = min(max(wrappedValue, range.lowerBound), range.upperBound)
}
}
struct CounterView: View {
@State @Clamped(0...100) private var counter = 0
var body: some View {
Stepper("Count: \(counter)", value: $counter)
}
}
The problem is the composition of @State and @Clamped on one property. In a real project, the second wrapper may come from an internal library or a third-party package.
Cause
SwiftUI’s @State is a Swift macro in Xcode 27. For a declaration such as @State private var counter, its expansion synthesizes backing storage named _counter. The additional property wrapper also needs backing storage with that name. Because both declarations generate _counter, the compiler reports an invalid redeclaration and stops the build.
Important: This is not a corrupted cache or Derived Data problem. The source structure that composes @State with another property wrapper is incompatible with Xcode 27’s macro-based implementation.
Affected versions and conditions
- The SwiftUI source is compiled with Xcode 27.
- Another property wrapper is composed with
@Stateon the same property. - Both transformations attempt to synthesize the same underscore-prefixed backing-storage name.
Apple listed this diagnostic as a known Xcode 27 source incompatibility in TN3211, first published June 8, 2026. Apple’s documented remediation is to remove the additional property wrapper from the @State property. This is a source migration, not a temporary bug with a future fixed version to wait for.
Recommended fix
1. Remove the wrapper composed with @State
struct CounterView: View {
@State private var counter = 0
var body: some View {
Stepper(
"Count: \(counter)",
value: Binding(
get: { counter },
set: { counter = min(max($0, 0), 100) }
)
)
}
}
Keep @State as the single owner of the view state. Move any transformation or validation previously supplied by the second wrapper into a separate location, such as a custom Binding setter.
2. Move behavior into a regular method
struct CounterView: View {
@State private var counter = 0
private func setCounter(_ newValue: Int) {
counter = min(max(newValue, 0), 100)
}
var body: some View {
VStack {
Text("Count: \(counter)")
Button("Increase") {
setCounter(counter + 1)
}
}
}
}
Normalization, validation, and logging can be made explicit in a method while @State remains the only storage mechanism.
3. Move complex rules into the state model
For more complex behavior, put the rule in a constrained value type or an @Observable model and hold that model as one @State property in the view. Do not automatically compose wrappers or macros inside the model; verify the documented compatibility of each attribute first.
Alternatives
- Use a custom
Binding(get:set:)when only read/write conversion is required. - Normalize a value in an event handler or
onChangewhen correction after input is acceptable. - Use a dedicated value type when the constraint must be true everywhere, not only in the view.
- If the extra wrapper no longer provides useful behavior, remove it and keep only
@State.
How to verify the fix
- Confirm that the affected property has only the
@Stateattribute. - Run Product > Clean Build Folder and rebuild the target.
- Check Issue Navigator to confirm that
invalid redeclaration of synthesized propertyis gone. - Change the value in a preview, simulator, or device and verify that validation or clamping previously supplied by the wrapper still works.
- Build both Debug and Release, and check conditional-compilation branches for another composed declaration.
Cautions
Distinguish similar diagnostics. A related message can also occur when property wrappers such as @Published are used inside an @Observable type. This article specifically covers a SwiftUI view in Xcode 27 where @State is composed with an additional property wrapper. Check the error location and macro expansion before removing an attribute.
- Deleting Derived Data cannot resolve a backing-storage collision encoded in the source.
- After removing the wrapper, preserve any validation, persistence, or conversion behavior that it previously supplied.
@Stateis intended for transient UI state owned by a view. For persistent or externally owned data, consider@AppStorage,@Binding, or a model with clearer ownership.
Summary
invalid redeclaration of synthesized property '_x' occurs because Xcode 27’s macro-based @State and another property wrapper both try to synthesize the same _x backing storage. Follow Apple’s guidance and remove the additional wrapper. Move its behavior into a Binding, a method, or the state model, then verify both the clean build and the runtime behavior that the wrapper previously enforced.
Official references
- Apple TN3211: Resolving SwiftUI source incompatibilities for State and ContentBuilder (first published June 8, 2026)
- Apple WWDC26: What’s new in SwiftUI (the
@Statemacro and lazy initialization)
