Related issues
Version info
node: v22.21.1
firebase-functions: 7.2.3
firebase-tools: N/A (not a deployment issue)
firebase-admin: ^13.0.0
Test case
import { onMessagePublished } from "firebase-functions/v2/pubsub";
export const myFunction = onMessagePublished("my-topic", (event) => {
// V2 canonical access path — broken in 7.2.3
const payload = event.data.message.json;
console.log(payload); // undefined
// V1 compat path — still works
const payloadV1 = event.message.json;
console.log(payloadV1); // { hello: "world" }
});
Steps to reproduce
- Create a Cloud Function using onMessagePublished as shown above.
- Deploy with firebase-functions@7.2.3.
- Publish a JSON message to the topic (e.g. {"hello": "world"}).
- Access event.data.message.json inside the handler.
Expected behavior
event.data.message.json should return the parsed JSON payload ({ hello: "world" }), as it did in firebase-functions@7.2.2. The event.data.message object should be an instance of the Message class, which provides a .json getter that base64-decodes and JSON-parses the raw message data.
Actual behavior
event.data.message.json returns undefined. The event.data.message object is a raw POJO ({ data: "", messageId: "...", ... }) without the .json getter.
Root cause: In src/v2/providers/pubsub.ts (lines 343–348), the onMessagePublished wrapper creates a Message instance from the raw message but stores it only in a local variable (v2Message). It never assigns it back to event.data.message. The old patchV1Compat function (replaced in commit 01ed20c) did perform this assignment:
// Old code in patchV1Compat (7.2.2) — this mutation was lost:
(pubsubData as any).message = new Message(pubsubData.message);
// New code in onMessagePublished (7.2.3) — local variable only, never assigned back:
let v2Message: Message;
v2Message = pubsubData.message instanceof Message
? pubsubData.message
: new Message(pubsubData.message);
// Missing: (pubsubData as any).message = v2Message;
Workaround: Use the V1 compat accessor event.message.json, or manually decode:
const payload = JSON.parse(Buffer.from(event.data.message.data, "base64").toString());
Were you able to successfully deploy your functions?
Yes. Deployment succeeds without errors. The issue is a runtime behavior regression, the function deploys and triggers correctly, but event.data.message is not wrapped in the Message class, so .json is undefined.
Related issues
Version info
node: v22.21.1
firebase-functions: 7.2.3
firebase-tools: N/A (not a deployment issue)
firebase-admin: ^13.0.0
Test case
import { onMessagePublished } from "firebase-functions/v2/pubsub";
export const myFunction = onMessagePublished("my-topic", (event) => {
// V2 canonical access path — broken in 7.2.3
const payload = event.data.message.json;
console.log(payload); // undefined
// V1 compat path — still works
const payloadV1 = event.message.json;
console.log(payloadV1); // { hello: "world" }
});
Steps to reproduce
Expected behavior
event.data.message.json should return the parsed JSON payload ({ hello: "world" }), as it did in firebase-functions@7.2.2. The event.data.message object should be an instance of the Message class, which provides a .json getter that base64-decodes and JSON-parses the raw message data.
Actual behavior
event.data.message.json returns undefined. The event.data.message object is a raw POJO ({ data: "", messageId: "...", ... }) without the .json getter.
Root cause: In src/v2/providers/pubsub.ts (lines 343–348), the onMessagePublished wrapper creates a Message instance from the raw message but stores it only in a local variable (v2Message). It never assigns it back to event.data.message. The old patchV1Compat function (replaced in commit 01ed20c) did perform this assignment:
// Old code in patchV1Compat (7.2.2) — this mutation was lost:
(pubsubData as any).message = new Message(pubsubData.message);
// New code in onMessagePublished (7.2.3) — local variable only, never assigned back:
let v2Message: Message;
v2Message = pubsubData.message instanceof Message
? pubsubData.message
: new Message(pubsubData.message);
// Missing: (pubsubData as any).message = v2Message;
Workaround: Use the V1 compat accessor event.message.json, or manually decode:
const payload = JSON.parse(Buffer.from(event.data.message.data, "base64").toString());
Were you able to successfully deploy your functions?
Yes. Deployment succeeds without errors. The issue is a runtime behavior regression, the function deploys and triggers correctly, but event.data.message is not wrapped in the Message class, so .json is undefined.