apache/rocketmq · error · IllegalArgumentException

Update topic reserveTime not supported

Error message

Update topic reserveTime not supported

What it means

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.

Source

Thrown at broker/src/main/java/org/apache/rocketmq/broker/topic/TopicConfigManager.java:559

        }

        updateDataVersion();
    }

    public void updateTopicConfig(final TopicConfig topicConfig) {
        updateSingleTopicConfigWithoutPersist(topicConfig);
        this.persist(topicConfig.getTopicName(), topicConfig);
    }

    public void updateTopicConfigList(final List<TopicConfig> topicConfigList) {
        topicConfigList.forEach(this::updateSingleTopicConfigWithoutPersist);
        this.persist();
    }

    private synchronized void updateTieredStoreTopicMetadata(final TopicConfig topicConfig, Map<String, String> newAttributes) {
        if (!(brokerController.getMessageStore() instanceof TieredMessageStore)) {
            if (newAttributes.get(TopicAttributes.TOPIC_RESERVE_TIME_ATTRIBUTE.getName()) != null) {
                throw new IllegalArgumentException("Update topic reserveTime not supported");
            }
            return;
        }

        String topic = topicConfig.getTopicName();
        long reserveTime = TopicAttributes.TOPIC_RESERVE_TIME_ATTRIBUTE.getDefaultValue();
        String attr = topicConfig.getAttributes().get(TopicAttributes.TOPIC_RESERVE_TIME_ATTRIBUTE.getName());
        if (attr != null) {
            reserveTime = Long.parseLong(attr);
        }

        log.info("Update tiered storage metadata, topic {}, reserveTime {}", topic, reserveTime);
        TieredMessageStore tieredMessageStore = (TieredMessageStore) brokerController.getMessageStore();
        MetadataStore metadataStore = tieredMessageStore.getMetadataStore();
        TopicMetadata topicMetadata = metadataStore.getTopic(topic);
        if (topicMetadata == null) {
            metadataStore.addTopic(topic, reserveTime);
        } else if (topicMetadata.getReserveTime() != reserveTime) {

View on GitHub (pinned to 293f588571)

Solutions

  1. Remove the 'reservedTime' attribute from the topic-update request, or
  2. Enable tiered storage (set tieredStorageTierBackend / enableTieredStorage so MessageStore is TieredMessageStore) before setting reserveTime.
  3. Make scripts conditional: only send reserveTime when the broker advertises tiered storage.

Example fix

// before
mqadmin updateTopic -n ns:9876 -c TestCluster -t TopicA \
  --attributes reservedTime=86400000  // non-tiered broker -> IllegalArgumentException

// after
mqadmin updateTopic -n ns:9876 -c TestCluster -t TopicA  // no reserveTime on non-tiered store
// or enable tiered storage on the broker first, then set the attribute
Defensive patterns

Strategy: validation

Validate before calling

boolean tiered = brokerController.getMessageStore() instanceof TieredMessageStore;
if (!tiered) {
    attributes.remove(TopicAttributes.TOPIC_RESERVE_TIME_ATTRIBUTE.getName());
}

Type guard

boolean reserveTimeAllowed(MessageStore store) { return store instanceof TieredMessageStore; }

Prevention

When it happens

Trigger: updateTopicConfig with attributes containing 'reservedTime' (TopicAttributes.TOPIC_RESERVE_TIME_ATTRIBUTE) while running the default local store (enableTieredStorage=false / TieredMessageStore not in use).

Common situations: 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.

Related errors


AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14). Data as JSON: /api/errors/23a13ccc63085342. Report an issue: GitHub.