microg/GmsCore · error · IllegalArgumentException

No registration token!

Error message

No registration token!

What it means

GcmPubSub.subscribe throws IllegalArgumentException when the registration token is null or empty. Subscribing a device to a topic requires a valid InstanceID/GCM registration token identifying the app instance.

Source

Thrown at play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmPubSub.java:91

     * sent to that topic.
     * <p/>
     * The topic sender must be authorized to send messages to the
     * app instance. To authorize it, call {@link com.google.android.gms.iid.InstanceID#getToken(java.lang.String, java.lang.String)}
     * with the sender ID and {@link com.google.android.gms.gcm.GoogleCloudMessaging#INSTANCE_ID_SCOPE}
     * <p/>
     * Do not call this function on the main thread.
     *
     * @param registrationToken {@link com.google.android.gms.iid.InstanceID} token that authorizes topic
     *                          sender to send messages to the app instance.
     * @param topic             developer defined topic name.
     *                          Must match the following regular expression:
     *                          "/topics/[a-zA-Z0-9-_.~%]{1,900}".
     * @param extras            (optional) additional information.
     * @throws IOException if the request fails.
     */
    public void subscribe(String registrationToken, String topic, Bundle extras) throws IOException {
        if (TextUtils.isEmpty(registrationToken))
            throw new IllegalArgumentException("No registration token!");
        if (TextUtils.isEmpty(topic) || !topicPattern.matcher(topic).matches())
            throw new IllegalArgumentException("Invalid topic: " + topic);

        if (extras == null) extras = new Bundle();
        extras.putString(EXTRA_TOPIC, topic);
        instanceId.getToken(registrationToken, topic, extras);
    }

    /**
     * Unsubscribes an app instance from a topic, stopping it from receiving
     * any further messages sent to that topic.
     * <p/>
     * Do not call this function on the main thread.
     *
     * @param registrationToken {@link com.google.android.gms.iid.InstanceID} token
     *                          for the same sender and scope that was previously
     *                          used for subscribing to the topic.
     * @param topic             from which to stop receiving messages.

View on GitHub (pinned to 157c9d86ac)

Solutions

  1. Obtain a token first: String token = InstanceID.getInstance(context).getToken(senderId, GoogleCloudMessaging.INSTANCE_ID_SCOPE); then subscribe.
  2. Check TextUtils.isEmpty(token) before calling subscribe.
  3. Persist and reuse a valid token; retry registration on failure before subscribing.

Example fix

// before
String token = prefs.getString("gcm_token", null);
pubSub.subscribe(token, "/topics/news", null); // "No registration token!"

// after
String token = prefs.getString("gcm_token", null);
if (token == null) {
    token = InstanceID.getInstance(context).getToken(senderId, GoogleCloudMessaging.INSTANCE_ID_SCOPE);
}
pubSub.subscribe(token, "/topics/news", null);
Defensive patterns

Strategy: validation

Validate before calling

if (TextUtils.isEmpty(token)) {
    token = InstanceID.getInstance(context).getToken(senderId, GoogleCloudMessaging.INSTANCE_ID_SCOPE);
}

Type guard

boolean hasToken(String t) { return t != null && !t.trim().isEmpty(); }

Try / catch

try {
    pubSub.subscribe(token, topic, null);
} catch (IllegalArgumentException e) {
    Log.w(TAG, "Subscribe aborted: " + e.getMessage());
} catch (IOException e) {
    retrySubscribeLater();
}

Prevention

When it happens

Trigger: Calling subscribe(token, topic, extras) before InstanceID.getToken() has completed or after it failed, passing an empty string, or reading the token from storage where it was never persisted.

Common situations: Subscribe called in onCreate before registration callback returns; token retrieval failed earlier (IOException) and the null/empty result was cached; race between token refresh and topic subscribe.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06). Data as JSON: /api/errors/9b274e5d9d99a76a. Report an issue: GitHub.