firebase-ios-sdk icon indicating copy to clipboard operation
firebase-ios-sdk copied to clipboard

Firestore decode fails for an optional @ServerTimestamp field

Open fanwgwg opened this issue 7 months ago • 10 comments

Description

Decoding a Firestore document into a Codable model with an optional field marked @ServerTimestamp (e.g., var myTimestamp: Timestamp?) fails if the field is absent in the document. This is commonly needed let's say we're adding a new server write timestamp to an existing data model.

Reproducing the issue

struct TestModel: Codable {
    @ServerTimestamp var optionalServerTs: Date?
    var regularOptional: String?
    var name: String
}

let docRef = db.collection("tests").document("missingOptionalTsDoc")
docRef.getDocument(as: TestModel.self) { result in
    // Decoding fails here if 'optionalServerTs' is missing
    // but 'regularOptional' (if missing) would correctly be nil.
}

Firebase SDK Version

11.12.0

Xcode Version

16.4

Installation Method

Swift Package Manager

Firebase Product(s)

Firestore

Targeted Platforms

iOS

Relevant Log Output

keyNotFound(CodingKeys(stringValue: "lastServerWriteTimestamp", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"lastServerWriteTimestamp\", intValue: nil) (\"lastServerWriteTimestamp\").", underlyingError: nil))

If using Swift Package Manager, the project's Package.resolved

No response

If using CocoaPods, the project's Podfile.lock

No response

fanwgwg avatar May 23 '25 07:05 fanwgwg

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

google-oss-bot avatar May 23 '25 07:05 google-oss-bot

Hi @fanwgwg, thank you for raising this issue. While I am looking into this, could you please try:

  1. change the Date to Timestamp: https://github.com/firebase/firebase-ios-sdk/blob/4f6c342424df416d78dfc12d08c97769fd4e1152/Firestore/Swift/Source/Codable/ServerTimestamp.swift#L64
  2. give it a default nil value

milaGGL avatar May 23 '25 19:05 milaGGL

Hey @fanwgwg. We need more information to resolve this issue but there hasn't been an update in 5 weekdays. I'm marking the issue as stale and if there are no new updates in the next 5 days I will close it automatically.

If you have more information that will help us get to the bottom of this, just add a comment!

google-oss-bot avatar Jul 17 '25 01:07 google-oss-bot

@milaGGL Yes the same problem exists with Timestamp

fanwgwg avatar Jul 17 '25 02:07 fanwgwg

HI @fanwgwg

could you please try if this approach can solve your problem?

let container = try decoder.singleValueContainer()
    if container.decodeNil() {
      value = nil
    } else {
      do {
         value = try Value.wrap(container.decode(Timestamp.self))
      } catch SPECIFIC_ERR {
         value = nil
      }
    }

cherylEnkidu avatar Jul 18 '25 20:07 cherylEnkidu

Hey @fanwgwg. We need more information to resolve this issue but there hasn't been an update in 5 weekdays. I'm marking the issue as stale and if there are no new updates in the next 5 days I will close it automatically.

If you have more information that will help us get to the bottom of this, just add a comment!

google-oss-bot avatar Jul 25 '25 18:07 google-oss-bot

Since there haven't been any recent updates here, I am going to close this issue.

@fanwgwg if you're still experiencing this problem and want to continue the discussion just leave a comment here and we are happy to re-open this.

google-oss-bot avatar Aug 01 '25 18:08 google-oss-bot

Reopened due to a new comment from @fanwgwg in #15293 . Copying that comment below:

Why a fix is still needed Unexpected Behavior: The current implementation breaks standard Swift Codable convention. Developers expect an optional property (var myDate: Date?) to become nil if its key is missing, but @ServerTimestamp instead throws a keyNotFound error. Wasted Developer Time: This forces developers to debug a common scenario (like adding a new timestamp field), find the workaround, and apply boilerplate code. Defeats the Purpose: Property wrappers like @ServerTimestamp exist to reduce boilerplate, but this issue forces developers to add more. The Solution The @ServerTimestamp decoder should gracefully handle a missing key for optional types by decoding the property to nil.

Fixing this in the SDK would make the API more intuitive, align it with standard Swift behavior, and save developers from unnecessary friction. Thank you.

The team reviewed this today. It does seem like something that should be fixed. But I need to follow up with @cherylEnkidu to determine if there was something previously blocking that fix.

MarkDuckworth avatar Sep 05 '25 19:09 MarkDuckworth

Hey @fanwgwg. We need more information to resolve this issue but there hasn't been an update in 5 weekdays. I'm marking the issue as stale and if there are no new updates in the next 5 days I will close it automatically.

If you have more information that will help us get to the bottom of this, just add a comment!

google-oss-bot avatar Sep 12 '25 18:09 google-oss-bot

Keeping this open. The team is investigating a fix.

MarkDuckworth avatar Sep 12 '25 18:09 MarkDuckworth