{"record":{"id":"391979a84d4001e5","repo":"neondatabase/neon","slug":"no-updated-field","errorCode":null,"errorMessage":"no 'updated' field","messagePattern":"no 'updated' field","errorType":"exception","errorClass":"DownloadError","httpStatus":null,"severity":"error","filePath":"libs/remote_storage/src/gcs_bucket.rs","lineNumber":285,"sourceCode":"                \n            let res = response.json::<GCSListResponse>()\n                .await\n                .map_err(|e| DownloadError::Other(e.into()))?;\n                    \n            // fill up our results vec, \n            continuation_token = res.next_page_token;\n            \n            let version_listing = \n                res.items\n                    .ok_or_else(|| DownloadError::Other(anyhow::anyhow!(\"no items returned\")))?\n                    .into_iter()\n                    .map(| GCSObject { name, updated, time_deleted, generation, .. } | {\n                        // don't `filter_map`, a `None` for `last_modified` ('updated') is bad for\n                        // time travel, so catch it.\n                        if updated.is_none() {\n                           return Err(\n                               DownloadError::Other(\n                                   anyhow::anyhow!(\"no 'updated' field\")\n                               )\n                           )\n                        }\n                        Ok(\n                            GCSVersion {\n                                key: self.gcs_object_to_relative_path(&name),\n                                last_modified: to_system_time(updated).unwrap(),\n                                id: VersionId(generation.expect(\"no version id\")),\n                                time_deleted: to_system_time(time_deleted),\n                            }\n                        )\n                    }).collect::<Result<Vec<GCSVersion>, _>>();\n                \n            versions.versions.extend(version_listing?);\n\n            if let Some(max_keys) = max_keys {\n                if versions.versions.len() >= max_keys.get().try_into().unwrap() {\n                    return Err(DownloadError::Other(","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/neondatabase/neon/blob/8f60b04da47ffefe0e52bda2440134b42874eb75/libs/remote_storage/src/gcs_bucket.rs#L267-L303","documentation":"Every object in the GCS version listing must carry an updated (last-modified, RFC 3339) timestamp because time travel relies on it for ordering; the code deliberately does not filter_map so that a None aborts the listing. GCS normally always returns updated, so a None indicates a malformed or unexpected API response rather than normal operation.","triggerScenarios":"list_versions where any listed object version lacks the updated JSON field — an API shape change, a partially-initialized object record, or a GCS-compatible gateway/emulator that drops the field.","commonSituations":"S3-compatible proxies or emulators fronting GCS that omit fields; GCP API behavior drift; extremely rare metadata anomalies on freshly created objects.","solutions":["Retry the listing — transient malformed responses are rare but possible","Capture the raw JSON body of the list response and confirm updated is truly absent versus a deserialization mismatch in GCSObject","Remove or fix any GCS-compatible intermediary so responses come from the real JSON API","If reproducible on one object, inspect that object's metadata directly (gsutil stat / objects.get) and report upstream"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Rare, anomalous-response error: retry once, then surface with the key for diagnosis.\nlet versions = match storage.list_versions(key, None, &cancel).await {\n    Ok(v) => v,\n    Err(DownloadError::Other(e)) if format!(\"{e:#}\").contains(\"no 'updated' field\") => {\n        tracing::warn!(\"malformed listing response for {key}, retrying once\");\n        tokio::time::sleep(Duration::from_millis(500)).await;\n        storage.list_versions(key, None, &cancel).await?\n    }\n    Err(e) => return Err(e),\n};","preventionTips":["Avoid GCS-compatible proxies/emulators in production paths; talk to the real JSON API","Log raw list responses (trace level) in environments where anomalies recur","Treat single-field-missing errors as data-quality signals: capture and report, don't silently drop the version"],"tags":["gcs","google-cloud-storage","listing","deserialization","time-travel"],"backgroundTag":"missing-response-field","analyzedSha":"8f60b04da47ffefe0e52bda2440134b42874eb75","analyzedAt":"2026-08-16T23:39:28.135Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}