{"record":{"id":"992d77e44df73642","repo":"apache/beam","slug":"received-message-missing-publishtime-pubsubjsonclient","errorCode":null,"errorMessage":"Received message missing publishTime","messagePattern":"Received message missing publishTime","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/pubsub/PubsubJsonClient.java","lineNumber":205,"sourceCode":"      PubsubMessage pubsubMessage = message.getMessage();\n      if (pubsubMessage == null) {\n        continue;\n      }\n      Map<String, String> attributes = pubsubMessage.getAttributes();\n      if (attributes == null) {\n        attributes = new HashMap<>();\n      }\n\n      // Payload.\n      String dataStr = pubsubMessage.getData();\n      byte[] elementBytes = (dataStr == null) ? new byte[0] : pubsubMessage.decodeData();\n\n      // Timestamp.\n      long timestampMsSinceEpoch;\n      if (timestampAttribute == null || timestampAttribute.isEmpty()) {\n        String publishTime = pubsubMessage.getPublishTime();\n        if (publishTime == null) {\n          throw new IllegalStateException(\"Received message missing publishTime\");\n        }\n        timestampMsSinceEpoch = parseTimestampAsMsSinceEpoch(publishTime);\n      } else {\n        timestampMsSinceEpoch = extractTimestampAttribute(timestampAttribute, attributes);\n      }\n\n      // Ack id.\n      String ackId = message.getAckId();\n      if (ackId == null || ackId.isEmpty()) {\n        throw new IllegalStateException(\"Received message missing ackId\");\n      }\n\n      // Record id, if any.\n      @Nullable String recordId = null;\n      if (idAttribute != null) {\n        recordId = attributes.get(idAttribute);\n      }\n      if (recordId == null || recordId.isEmpty()) {","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/pubsub/PubsubJsonClient.java#L187-L223","documentation":"PubsubJsonClient.pull() converts a raw Pub/Sub response message into an IncomingMessage. When no custom timestamp attribute is configured, the client relies on the server-provided publishTime; if the API response omits it, IllegalStateException \"Received message missing publishTime\" is thrown. This indicates a malformed or incomplete response from the Pub/Sub service.","triggerScenarios":"Calling pull() on a PubsubJsonClient (no timestampAttribute configured) where a returned message has pubsubMessage.getPublishTime() == null — e.g. an unexpected/empty server response shape, or a stubbed/mocked Pub/Sub backend.","commonSituations":"Pointing the client at an emulator or proxy that doesn't set publishTime, API version drift changing response fields, or parsing responses from a service that mimics but does not fully implement the Pub/Sub API.","solutions":["Check whether a Pub/Sub emulator/proxy is in play and whether it populates publishTime in pulled messages.","Configure a custom timestamp attribute (withTimestampAttribute) so the client reads the timestamp from message attributes instead of the server field.","Upgrade the Google API client / Beam version in case of known response-shape incompatibilities.","Log the raw response to confirm which messages lack publishTime."],"exampleFix":"// before\nPubsubIO.readMessages().from(topic); // relies on server publishTime\n// after\nPubsubIO.readMessages().from(topic).withTimestampAttribute(\"myTimestampAttr\");","handlingStrategy":"validation","validationCode":"// guard against backends that omit publishTime by using an attribute\nif (pubsubMessage.getPublishTime() == null && (timestampAttribute == null || timestampAttribute.isEmpty())) {\n  throw new IllegalStateException(\"Backend does not supply publishTime; configure withTimestampAttribute\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  incoming = client.pull(request);\n} catch (IllegalStateException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"missing publishTime\")) {\n    // fall back to processing-time timestamp or switch to timestamp attribute\n  }\n}","preventionTips":["Test against the exact Pub/Sub backend (emulator vs real service) used in production.","Prefer an explicit timestamp attribute for deterministic event-time behavior.","Keep Google API client libraries up to date."],"tags":["java","pubsub","gcp","api-response","internal"],"backgroundTag":"unexpected-response-shape","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}