{"record":{"id":"7f9b0232a19c1f7a","repo":"microg/GmsCore","slug":"invalid-topic","errorCode":null,"errorMessage":"Invalid topic: ","messagePattern":"Invalid topic: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmPubSub.java","lineNumber":93,"sourceCode":"     * 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.\n     * @throws IOException if the request fails.\n     */","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/microg/GmsCore/blob/157c9d86ac46c195a86c2f15ab55c84036223f95/play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmPubSub.java#L75-L111","documentation":"GcmPubSub.subscribe throws IllegalArgumentException when the topic is empty or does not match the required pattern \"/topics/[a-zA-Z0-9-_.~%]{1,900}\". Topics must start with the literal prefix \"/topics/\" followed only by allowed characters, up to 900 chars.","triggerScenarios":"Calling subscribe(token, topic, extras) with topic like \"news\" (missing /topics/ prefix), containing spaces, slashes, unicode, or an empty string.","commonSituations":"Passing a raw topic name without the /topics/ prefix; building the topic from user input containing illegal characters; topic longer than 900 characters after prefixing.","solutions":["Format the topic as \"/topics/\" + name, using only [a-zA-Z0-9-_.~%] characters in the name.","Sanitize/normalize user- or server-provided topic names before subscribing.","Validate with a regex before calling: topic.matches(\"/topics/[a-zA-Z0-9-_.~%]{1,900}\")."],"exampleFix":"// before\npubSub.subscribe(token, \"news\", null); // Invalid topic: news\n\n// after\nString topic = \"/topics/news\"; // matches /topics/[a-zA-Z0-9-_.~%]{1,900}\npubSub.subscribe(token, topic, null);","handlingStrategy":"validation","validationCode":"private static final Pattern TOPIC = Pattern.compile(\"/topics/[a-zA-Z0-9-_.~%]{1,900}\");\nboolean isValidTopic(String t) { return t != null && TOPIC.matcher(t).matches(); }","typeGuard":null,"tryCatchPattern":"try {\n    pubSub.subscribe(token, topic, null);\n} catch (IllegalArgumentException e) {\n    Log.w(TAG, \"Invalid topic: \" + e.getMessage());\n}","preventionTips":["Always prefix topic names with \"/topics/\"","Restrict topic names to [a-zA-Z0-9-_.~%]","Validate topics at creation time, before they reach subscribe"],"tags":["gcm","android","push-notifications","pubsub","topic-format"],"backgroundTag":"invalid-argument-format","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"}