{"record":{"id":"23a13ccc63085342","repo":"apache/rocketmq","slug":"update-topic-reservetime-not-supported","errorCode":null,"errorMessage":"Update topic reserveTime not supported","messagePattern":"Update topic reserveTime not supported","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"broker/src/main/java/org/apache/rocketmq/broker/topic/TopicConfigManager.java","lineNumber":559,"sourceCode":"        }\n\n        updateDataVersion();\n    }\n\n    public void updateTopicConfig(final TopicConfig topicConfig) {\n        updateSingleTopicConfigWithoutPersist(topicConfig);\n        this.persist(topicConfig.getTopicName(), topicConfig);\n    }\n\n    public void updateTopicConfigList(final List<TopicConfig> topicConfigList) {\n        topicConfigList.forEach(this::updateSingleTopicConfigWithoutPersist);\n        this.persist();\n    }\n\n    private synchronized void updateTieredStoreTopicMetadata(final TopicConfig topicConfig, Map<String, String> newAttributes) {\n        if (!(brokerController.getMessageStore() instanceof TieredMessageStore)) {\n            if (newAttributes.get(TopicAttributes.TOPIC_RESERVE_TIME_ATTRIBUTE.getName()) != null) {\n                throw new IllegalArgumentException(\"Update topic reserveTime not supported\");\n            }\n            return;\n        }\n\n        String topic = topicConfig.getTopicName();\n        long reserveTime = TopicAttributes.TOPIC_RESERVE_TIME_ATTRIBUTE.getDefaultValue();\n        String attr = topicConfig.getAttributes().get(TopicAttributes.TOPIC_RESERVE_TIME_ATTRIBUTE.getName());\n        if (attr != null) {\n            reserveTime = Long.parseLong(attr);\n        }\n\n        log.info(\"Update tiered storage metadata, topic {}, reserveTime {}\", topic, reserveTime);\n        TieredMessageStore tieredMessageStore = (TieredMessageStore) brokerController.getMessageStore();\n        MetadataStore metadataStore = tieredMessageStore.getMetadataStore();\n        TopicMetadata topicMetadata = metadataStore.getTopic(topic);\n        if (topicMetadata == null) {\n            metadataStore.addTopic(topic, reserveTime);\n        } else if (topicMetadata.getReserveTime() != reserveTime) {","sourceCodeStart":541,"sourceCodeEnd":577,"githubUrl":"https://github.com/apache/rocketmq/blob/293f5885719fc4aa3619446a1900f58ccfcfdd29/broker/src/main/java/org/apache/rocketmq/broker/topic/TopicConfigManager.java#L541-L577","documentation":"TopicConfigManager.updateTieredStoreTopicMetadata rejects updates that carry the topic 'reserveTime' attribute when the broker's message store is NOT TieredMessageStore. The attribute controls tiered-storage data retention and only has meaning with tiered storage enabled, so setting it otherwise throws IllegalArgumentException.","triggerScenarios":"updateTopicConfig with attributes containing 'reservedTime' (TopicAttributes.TOPIC_RESERVE_TIME_ATTRIBUTE) while running the default local store (enableTieredStorage=false / TieredMessageStore not in use).","commonSituations":"Topic templates or Terraform/ops scripts that set reservedTime unconditionally; migrating configs from a tiered-storage cluster to a non-tiered one; enabling the attribute before enabling tiered storage.","solutions":["Remove the 'reservedTime' attribute from the topic-update request, or","Enable tiered storage (set tieredStorageTierBackend / enableTieredStorage so MessageStore is TieredMessageStore) before setting reserveTime.","Make scripts conditional: only send reserveTime when the broker advertises tiered storage."],"exampleFix":"// before\nmqadmin updateTopic -n ns:9876 -c TestCluster -t TopicA \\\n  --attributes reservedTime=86400000  // non-tiered broker -> IllegalArgumentException\n\n// after\nmqadmin updateTopic -n ns:9876 -c TestCluster -t TopicA  // no reserveTime on non-tiered store\n// or enable tiered storage on the broker first, then set the attribute","handlingStrategy":"validation","validationCode":"boolean tiered = brokerController.getMessageStore() instanceof TieredMessageStore;\nif (!tiered) {\n    attributes.remove(TopicAttributes.TOPIC_RESERVE_TIME_ATTRIBUTE.getName());\n}","typeGuard":"boolean reserveTimeAllowed(MessageStore store) { return store instanceof TieredMessageStore; }","tryCatchPattern":null,"preventionTips":["Only set reservedTime on brokers with tiered storage enabled.","Make topic templates conditional on the cluster's storage capability."],"tags":["rocketmq","broker","topic-config","tiered-storage","attribute","validation"],"backgroundTag":null,"analyzedSha":"293f5885719fc4aa3619446a1900f58ccfcfdd29","analyzedAt":"2026-08-14T11:50:13.822Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}