Skip to content

fix(notifications): show missing FCM token for user targets - #3353

Open
arimu1 wants to merge 7 commits into
openremote:mainfrom
arimu1:fix/3113-user-target-missing-fcm-error
Open

arimu1 wants to merge 7 commits into
openremote:mainfrom
arimu1:fix/3113-user-target-missing-fcm-error

Conversation

@arimu1

@arimu1 arimu1 commented Sep 26, 2026 •

Copy link
Copy Markdown

Description

Fixes #3113

When a push notification was sent to a USER or REALM target, console assets were only included in target mapping if they already had a non-empty FCM token in CONSOLE_PROVIDERS. Consoles without a token were dropped during mapping, which led to an empty target list and the misleading MISSING_TARGETS / "Notification targets must be set" error.

Direct ASSET console targets already kept consoles without a token so PushNotificationHandler.sendMessage could record No FCM token found for console: …. USER/REALM expansion now uses the same behaviour by not requiring a token in the asset query.

Checklist

  • 1. Acceptance criteria of the linked issue(s) are met
  • 2. Tests are written and all tests pass
  • 3. Changes are manually tested by you and the reviewer
  • 4. Documentation is written or updated

Test plan

  • ./gradlew :manager:compileJava :test:compileTestGroovy (JDK 21)
  • NotificationTest integration spec (requires docker compose -f profile/dev-testing.yml -p openremote up -d --no-build; Docker stack was not running in the implementator environment)
  • Manual: send push to a user whose linked console has no FCM token; notifications UI shows No FCM token found for console instead of targets must be set

@CLAassistant

CLAassistant commented Sep 26, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

USER and REALM push target expansion no longer requires a non-empty FCM
token in the asset query, so sendMessage can persist the existing
"No FCM token found for console" failure instead of MISSING_TARGETS.

Fixes openremote#3113
@arimu1
arimu1 force-pushed the fix/3113-user-target-missing-fcm-error branch from ab6e846 to a28cc9f Compare September 26, 2026 04:18

@MartinaeyNL MartinaeyNL left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First of all, thank you for creating a pull request! 🥳

You need to sign the contributor license agreement as stated by the bot above 😉
I'm happy to take a look after that's been resolved.

The dev-mode skip returned before the token check, so a user target with no token looked like success in integration tests.
@arimu1

arimu1 commented Oct 10, 2026

Copy link
Copy Markdown
Author

CLA is signed (license/cla is green).

The missing-FCM-token check now runs before the dev-mode skip. In the last integration run, NotificationTest expected a 400 for a user target with no token, but the skip returned success because FCM is not configured in that job. Tip 403996ef3 also includes current master.

The two GatewayTest failures in that run are outside this change.

@MartinaeyNL
MartinaeyNL requested a review from a team October 12, 2026 11:42
@MartinaeyNL MartinaeyNL added the Bug Error or issue in the system label Oct 12, 2026
@MartinaeyNL
MartinaeyNL requested a review from Ekhorn October 12, 2026 11:43

@Ekhorn Ekhorn left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an initial AI-assisted review.

The new step for a user whose consoles all lack a token covers the scenario from #3113, and checking the token before the dev-mode skip makes dev mode record the same failure as production.

Removing the token predicate from target expansion goes beyond the issue, though: browser and anonymous consoles, which never have an FCM token, become USER and REALM targets, so ordinary sends to those targets return 400 and store a failed notification per browser console. Details inline.

false,
new NameValuePredicate.Path(
PushNotificationMessage.TYPE, "data", "token")));
.types(ConsoleAsset.class);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dropping the token predicate widens USER, REALM and linked-user ASSET expansion to every console asset, not just FCM consoles that lost their token:

To keep the fix scoped to #3113, the token-less consoles could be mapped only when no console with a token is found for a target, so MISSING_TARGETS is replaced by a recorded failure without changing the result of normal sends. Limiting expansion to consoles whose push provider is fcm, the rule isLinkedToFcmProvider (manager/src/main/java/org/openremote/manager/notification/PushNotificationHandler.java:602-611) applies in start(), would also keep browser consoles out. A REALM step with a token-less console in the spec would pin down whichever behavior is chosen.

testUser3Console2Asset.getConsoleProviders().map {
it.get(PushNotificationMessage.TYPE)
}.get().getData().put("token", null)
assetStorageService.merge(testUser3Console2Asset)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The handler's token cache is updated by an asynchronous route on PERSISTENCE_TOPIC (a SEDA endpoint), so this send can still read the old token for testuser3Console2. When it does, that console is sent without an error and the console2Notifications assertion below times out. The step that clears the token on testuser3Console1 already waits for the cache before sending; the same wait here removes the race:

Suggested change
assetStorageService.merge(testUser3Console2Asset)
assetStorageService.merge(testUser3Console2Asset)
conditions.eventually {
assert pushNotificationHandler.consoleFCMTokenMap.get(testUser3Console2Asset.id) == null
}

A normal user or realm send still targets consoles that have an FCM token.
When none do, map FCM consoles so the missing token is recorded instead of
a missing-targets error, and wait for the token cache before that send.
…-error' into fix/3113-user-target-missing-fcm-error
@arimu1

arimu1 commented Oct 27, 2026

Copy link
Copy Markdown
Author

Addressed the review on tip d8a5deb1b (includes current main).

  • A user, realm, or linked-asset send still expands only to consoles that have an FCM token, so a browser console does not turn a normal send into a 400.
  • When that expansion is empty, FCM consoles (push version fcm) are mapped instead, and the send records "No FCM token found" rather than a missing-targets error. That is the Misleading 'targets must be set' error when sending to a user target without a valid FCM token #3113 case.
  • The all-missing step waits until consoleFCMTokenMap drops testuser3Console2 before sending.
  • :manager:compileJava and :test:compileGroovy passed. I did not rerun NotificationTest here (it needs the full manager stack).

@sonarqubecloud

Copy link
Copy Markdown

@Ekhorn
Ekhorn self-requested a review October 27, 2026 09:13

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Error or issue in the system

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Misleading 'targets must be set' error when sending to a user target without a valid FCM token

5 participants