{"record":{"id":"9b274e5d9d99a76a","repo":"microg/GmsCore","slug":"no-registration-token","errorCode":null,"errorMessage":"No registration token!","messagePattern":"No registration token!","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmPubSub.java","lineNumber":91,"sourceCode":"     * sent to that topic.\n     * <p/>\n     * The topic sender must be authorized to send messages to the\n     * app instance. To authorize it, call {@link com.google.android.gms.iid.InstanceID#getToken(java.lang.String, java.lang.String)}\n     * with the sender ID and {@link com.google.android.gms.gcm.GoogleCloudMessaging#INSTANCE_ID_SCOPE}\n     * <p/>\n     * Do not call this function on the main thread.\n     *\n     * @param registrationToken {@link com.google.android.gms.iid.InstanceID} token that authorizes topic\n     *                          sender to send messages to the app instance.\n     * @param topic             developer defined topic name.\n     *                          Must match the following regular expression:\n     *                          \"/topics/[a-zA-Z0-9-_.~%]{1,900}\".\n     * @param extras            (optional) additional information.\n     * @throws IOException if the request fails.\n     */\n    public void subscribe(String registrationToken, String topic, Bundle extras) throws IOException {\n        if (TextUtils.isEmpty(registrationToken))\n            throw new IllegalArgumentException(\"No registration token!\");\n        if (TextUtils.isEmpty(topic) || !topicPattern.matcher(topic).matches())\n            throw new IllegalArgumentException(\"Invalid topic: \" + topic);\n\n        if (extras == null) extras = new Bundle();\n        extras.putString(EXTRA_TOPIC, topic);\n        instanceId.getToken(registrationToken, topic, extras);\n    }\n\n    /**\n     * Unsubscribes an app instance from a topic, stopping it from receiving\n     * any further messages sent to that topic.\n     * <p/>\n     * Do not call this function on the main thread.\n     *\n     * @param registrationToken {@link com.google.android.gms.iid.InstanceID} token\n     *                          for the same sender and scope that was previously\n     *                          used for subscribing to the topic.\n     * @param topic             from which to stop receiving messages.","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/microg/GmsCore/blob/157c9d86ac46c195a86c2f15ab55c84036223f95/play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmPubSub.java#L73-L109","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Obtain a token first: String token = InstanceID.getInstance(context).getToken(senderId, GoogleCloudMessaging.INSTANCE_ID_SCOPE); then subscribe.","Check TextUtils.isEmpty(token) before calling subscribe.","Persist and reuse a valid token; retry registration on failure before subscribing."],"exampleFix":"// before\nString token = prefs.getString(\"gcm_token\", null);\npubSub.subscribe(token, \"/topics/news\", null); // \"No registration token!\"\n\n// after\nString token = prefs.getString(\"gcm_token\", null);\nif (token == null) {\n    token = InstanceID.getInstance(context).getToken(senderId, GoogleCloudMessaging.INSTANCE_ID_SCOPE);\n}\npubSub.subscribe(token, \"/topics/news\", null);","handlingStrategy":"validation","validationCode":"if (TextUtils.isEmpty(token)) {\n    token = InstanceID.getInstance(context).getToken(senderId, GoogleCloudMessaging.INSTANCE_ID_SCOPE);\n}","typeGuard":"boolean hasToken(String t) { return t != null && !t.trim().isEmpty(); }","tryCatchPattern":"try {\n    pubSub.subscribe(token, topic, null);\n} catch (IllegalArgumentException e) {\n    Log.w(TAG, \"Subscribe aborted: \" + e.getMessage());\n} catch (IOException e) {\n    retrySubscribeLater();\n}","preventionTips":["Always register with InstanceID.getToken before subscribing","Persist the token and refresh on INSTANCE_ID_RESET broadcasts","Guard all subscribe/unsubscribe calls with an empty check"],"tags":["gcm","android","push-notifications","pubsub","empty-token"],"backgroundTag":"empty-required-field","analyzedSha":"157c9d86ac46c195a86c2f15ab55c84036223f95","analyzedAt":"2026-09-06T17:27:33.892Z","contentChangedAt":"2026-09-06T17:27:33.892Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}