firebase / firebase/firebase-tools
Data Connect onMutationExecuted Cloud Functions triggers do not fire in the emulator
- Dominant language
- TypeScript
- Stars
- 4.5k
- Forks
- 1.3k
- Avg merge
- 1d 12h
- Merged PRs (30d)
- 84
Description
### [REQUIRED] Environment info
**firebase-tools:** 15.21.0 (bundled Data Connect emulator toolkit 3.4.11)
**Platform:** macOS (Darwin 25.4). Not platform-specific — the missing dispatch is inside the emulator, so it reproduces on any host.
Other relevant versions: `firebase-functions` 7.0.0, `firebase-admin` 13.6.0, Cloud Functions runtime Node 24. The Functions region matches the Data Connect service location (`us-east4`), as the [triggers docs](https://firebase.google.com/docs/functions/data-connect-events) require for events to fire when deployed.
### [REQUIRED] Test case
A Data Connect service with one connector (`main`) exposing a simple mutation, plus a Cloud Function that subscribes to it via `onMutationExecuted`:
```graphql
# dataconnect/main/example.gql
mutation CreateThing($name: String!) @auth(level: PUBLIC) {
thing_insert(data: { name: $name })
}
```
```ts
// functions/src/index.ts (built to lib/ before starting the emulator)
import { onMutationExecuted } from "firebase-functions/dataconnect";
import * as logger from "firebase-functions/logger";
export const onThingCreated = onMutationExecuted(
{ service: "example-service", connector: "main", operation: "CreateThing", region: "us-east4" },
(event) => {
logger.info("onThingCreated FIRED", { vars: event.data.payload.variables });
},
);
```
### [REQUIRED] Steps to reproduce
1. Build functions (`npm run build`) so `lib/` is current.
2. Start the suite: `firebase emulators:start --only auth,dataconnect,functions`.
3. Execute the mutation against the Data Connect emulator by any client path — the VS Code extension's **Run (local)**, the generated SDK pointed at the emulator, or:
`firebase dataconnect:execute --emulator main CreateThing '{"name":"hello"}'`
4. Watch the Functions emulator logs.
### [REQUIRED] Expected behavior
The emulator dispatches the `onMutationExecuted` event to the local Functions runtime and `onThingCreated` runs — the `onThingCreated FIRED` line appears — the same as when the function is deployed to a live project.
### [REQUIRED] Actual behavior
The mutation succeeds and writes the row, but the Cloud Function is **never invoked** under the emulator: no `onThingCreated FIRED` log, no error, nothing is dispatched. The same function fires as expected once deployed to a live project (this is the documented production behavior — our deployed `onImageFileCreated` thumbnail trigger, also an `onMutationExecuted` trigger, fires normally), so the handler and its filter are correct — the emulator simply doesn't deliver Data Connect mutation events to Functions.
The only way we've found to exercise such a handler locally is to import the built handler and call `.run(syntheticEvent)` directly against a live emulator (with `DATA_CONNECT_EMULATOR_HOST` set) — i.e. manually simulate the dispatch the emulator never performs. This affects every `onMutationExecuted` trigger, not one specific operation.
Notes / related:
- Neither the [Data Connect triggers doc](https://firebase.google.com/docs/functions/data-connect-events) nor the [emulator suite doc](https://firebase.google.com/docs/sql-connect/data-connect-emulator-suite) mentions local emulator support for these triggers, so this may be a known/undocumented limitation rather than a regression. If so, it would help a lot to (a) state it explicitly in the docs and (b) put emulator dispatch on the roadmap — local iteration on trigger logic is otherwise impossible without deploying.
- Possibly related: #8379 (Cloud Functions couldn't query Data Connect in the emulator) and #10553 (`@refresh(onMutationExecuted:)` not firing across connectors).
Contributor guide
Research direction
Start with the Data Connect and Functions emulator entry points exercised by `firebase emulators:start --only auth,dataconnect,functions`, using `functions/src/index.ts` and the `firebase dataconnect:execute --emulator` command as the reproduction. Verify that a successful `CreateThing` mutation reaches the `onMutationExecuted` handler and produces the `onThingCreated FIRED` log; the issue is done when local dispatch works or the supported limitation is documented.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js, typescript
- Domain
- backend, devtools, testing-qa
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100