{"record":{"id":"f9ebc7e1a0608c81","repo":"aeron-io/aeron","slug":"null-channeltag-null-pubsubtag","errorCode":null,"errorMessage":"null == channelTag && null != pubSubTag","messagePattern":"null == channelTag && null != pubSubTag","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"aeron-client/src/main/java/io/aeron/ChannelUriStringBuilder.java","lineNumber":1254,"sourceCode":"    {\n        return tags(channelUri.get(TAGS_PARAM_NAME));\n    }\n\n    /**\n     * Set the tags to the specified channel and publication/subscription tag {@link ChannelUri}. The\n     * publication/subscription may be null. If channel tag is null, then the pubSubTag must be null.\n     *\n     * @param channelTag optional value for the channel tag.\n     * @param pubSubTag  option value for the publication/subscription tag.\n     * @return this for a fluent API.\n     * @throws IllegalArgumentException if channelTag is null and pubSubTag is not.\n     * @see CommonContext#TAGS_PARAM_NAME\n     */\n    public ChannelUriStringBuilder tags(final Long channelTag, final Long pubSubTag)\n    {\n        if (null == channelTag && null != pubSubTag)\n        {\n            throw new IllegalArgumentException(\"null == channelTag && null != pubSubTag\");\n        }\n\n        if (null == channelTag)\n        {\n            return tags((String)null);\n        }\n\n        return tags(channelTag + (null != pubSubTag ? \",\" + pubSubTag : \"\"));\n    }\n\n    /**\n     * Get the tags for a channel used by a publication or subscription. Tags can be used to identify or tag a\n     * channel so that a configuration can be referenced and reused.\n     *\n     * @return the tags for a channel, publication or subscription.\n     * @see CommonContext#TAGS_PARAM_NAME\n     * @see CommonContext#TAG_PREFIX\n     */","sourceCodeStart":1236,"sourceCodeEnd":1272,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-client/src/main/java/io/aeron/ChannelUriStringBuilder.java#L1236-L1272","documentation":"ChannelUriStringBuilder.tags(Long channelTag, Long pubSubTag) enforces that a pub/sub tag cannot exist without a channel tag, because in the URI encoding the pub-sub tag is only meaningful as the second element of the 'tags' parameter pair. Passing null channelTag with non-null pubSubTag is an invalid combination and throws immediately.","triggerScenarios":"Calling tags(null, 12345L) directly, or code paths where the channel tag is conditionally null but the pub/sub tag is always set.","commonSituations":"Refactoring where one tag is optional but the other is not; copying tag values from a configuration where only the second tag was populated; building tagged subscriptions with partially-filled tag pairs.","solutions":["Provide both tags: tags(channelTag, pubSubTag) with non-null Long values","If you only have the pub/sub tag, clear both: tags((String)null) or tags(null, null)","Fix the calling logic so channelTag is generated/assigned whenever pubSubTag is set"],"exampleFix":"// before\nbuilder.tags(null, 1001L); // throws\n// after\nbuilder.tags(1000L, 1001L); // or builder.tags((String)null);","handlingStrategy":"validation","validationCode":"if (channelTag == null && pubSubTag != null) throw new IllegalArgumentException(\"pubSubTag requires a channelTag\");","typeGuard":null,"tryCatchPattern":"try { builder.tags(channelTag, pubSubTag); } catch (IllegalArgumentException e) { builder.tags((String)null); }","preventionTips":["Treat the tag pair as atomic: always set both or neither","Model tags as a single (channelTag, pubSubTag) record in your config layer","Remember URI semantics: the second tag only exists as part of the tags pair"],"tags":["aeron","uri-validation","invalid-argument-combination"],"backgroundTag":"conflicting-config-options","analyzedSha":"6d60124e15e35c11b49ba2e3c2c2858a09a18803","analyzedAt":"2026-09-12T11:17:07.683Z","contentChangedAt":"2026-09-12T11:17:07.683Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}