{"record":{"id":"0e652631d1a0c9ec","repo":"paperclipai/paperclip","slug":"invalid-response-photon-event-timestamp-is","errorCode":"invalid_response","errorMessage":"Photon event timestamp is invalid","messagePattern":"Photon event timestamp is invalid","errorType":"error_code","errorClass":"PhotonError","httpStatus":null,"severity":"error","filePath":"server/src/services/photon/receiver.ts","lineNumber":160,"sourceCode":"            \"Photon returned an invalid event sequence\",\n          );\n        if (++batchEvents > 100_000)\n          throw new PhotonError(\"history_gap\", \"Photon replay exceeds the supported recovery window\");\n        if (shared && sequence !== undefined && event.sequence < sequence && event.sequence > (original?.sequence ?? -1))\n          throw new PhotonError(\"history_gap\", \"Photon replay arrived out of order; the saved cursor was retained\");\n        if (sequence !== undefined && event.sequence <= sequence) continue;\n        if (!shared && sequence !== undefined && event.sequence !== sequence + 1)\n          throw new PhotonError(\n            \"history_gap\",\n            \"Photon event history is incomplete; operator recovery is required\",\n          );\n        // On the first connection, the server may retain only a tail of history.\n        // Establish that boundary explicitly; it is never allowed after a cursor.\n        sequence ??= event.sequence - 1;\n        if (event.type !== \"photon.ignored\") {\n          const occurredAt = new Date(event.occurredAt).getTime();\n          if (!Number.isFinite(occurredAt))\n            throw new PhotonError(\n              \"invalid_response\",\n              \"Photon event timestamp is invalid\",\n            );\n          if (occurredAt >= intakeAfter) await admit(event);\n        }\n        // admission must durably store or classify even irrelevant events.\n        if (!shared) await this.checkpoint(event.sequence);\n        sequence = event.sequence;\n      }\n      if (!completed && !this.stopped)\n        throw new PhotonError(\n          \"network\",\n          \"Photon catch-up ended before its checkpoint barrier\",\n        );\n    } finally {\n      await stream.close();\n      if (this.catchUpStream === stream) this.catchUpStream = undefined;\n    }","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/server/src/services/photon/receiver.ts#L142-L178","documentation":"Every non-ignored Photon event must carry a parseable occurredAt timestamp, because admission gating compares occurredAt to the intakeAfter threshold. If new Date(event.occurredAt).getTime() is not a finite number (missing field, malformed string, or epoch placeholder producing NaN), the response is considered invalid and the receiver throws invalid_response instead of admitting the event with unknown timing.","triggerScenarios":"catchUp() processes an event with type other than \"photon.ignored\" whose occurredAt is undefined, null, or a string unparseable by Date (e.g. \"\", \"not-a-date\"), so Number.isFinite(new Date(...).getTime()) fails.","commonSituations":"Photon server version regression that omits occurredAt from envelopes; a custom event producer emitting malformed timestamps; schema drift between the client's expected envelope shape and what the server sends; clock/serialization bugs producing null timestamps.","solutions":["Check the Photon server version for known occurredAt serialization regressions and upgrade to a fixed release","Log the raw event envelope to identify which producer emitted the malformed occurredAt and fix it at the source","Add upstream validation on the Photon server side so envelopes without a valid occurredAt are rejected before publication","If a third-party producer cannot be fixed immediately, downgrade such events to \"photon.ignored\" on the server so the client skips timestamp validation"],"exampleFix":"// before: producer omits timestamp\npublishEvent({ type: \"photon.created\", payload });\n// after: always stamp a valid occurredAt\npublishEvent({ type: \"photon.created\", occurredAt: new Date().toISOString(), payload });","handlingStrategy":"validation","validationCode":"function hasValidOccurredAt(event: PhotonEvent): boolean {\n  return event.type === \"photon.ignored\" || Number.isFinite(new Date(event.occurredAt).getTime());\n}\n// filter/validate envelopes before handing them to the receiver","typeGuard":"function isWellFormedEnvelope(e: unknown): e is PhotonEvent & { occurredAt: string } {\n  const ev = e as PhotonEvent;\n  return typeof ev?.occurredAt === \"string\" && !Number.isNaN(Date.parse(ev.occurredAt));\n}","tryCatchPattern":"try {\n  await receiver.catchUp(opts);\n} catch (e) {\n  if (e instanceof PhotonError && e.code === \"invalid_response\" && /timestamp/.test(e.message)) {\n    await quarantineLastEnvelopeAndReport(); // capture raw frame for producer debugging\n  } else throw e;\n}","preventionTips":["Pin and test against the Photon envelope schema version in CI","Add server-side rejection of envelopes lacking a valid occurredAt","Log raw malformed envelopes for producer attribution","Watch for Photon releases that touch event serialization"],"tags":["photon","invalid-response","timestamp","event-stream"],"backgroundTag":"unexpected-response-shape","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}