apolloconfig/apollo · warning · BadRequestException

Config text has repeated keys: %s, please check your input.

Error message

Config text has repeated keys: %s, please check your input.

What it means

BadRequestException (HTTP 400) raised by PropertyResolver while resolving the submitted namespace config text. isHasRepeatKey lower-cases each key and tracks collisions; if any key appears more than once the offending keys are collected and reported via the %s placeholder (formatted with Guava Strings.lenientFormat, so the Set prints as [k1, k2]).

Source

Thrown at apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/txtresolver/PropertyResolver.java:75

    // comment items
    List<ItemDTO> baseCommentItems = new LinkedList<>();
    // blank items
    List<ItemDTO> baseBlankItems = new LinkedList<>();
    if (!CollectionUtils.isEmpty(baseItems)) {

      baseCommentItems = baseItems.stream().filter(this::isCommentItem)
          .sorted(Comparator.comparing(ItemDTO::getLineNum))
          .collect(Collectors.toCollection(LinkedList::new));

      baseBlankItems = baseItems.stream().filter(this::isBlankItem)
          .sorted(Comparator.comparing(ItemDTO::getLineNum))
          .collect(Collectors.toCollection(LinkedList::new));
    }

    String[] newItems = configText.split(ITEM_SEPARATOR);
    Set<String> repeatKeys = new HashSet<>();
    if (isHasRepeatKey(newItems, repeatKeys)) {
      throw new BadRequestException("Config text has repeated keys: %s, please check your input.",
          repeatKeys);
    }

    ItemChangeSets changeSets = new ItemChangeSets();
    Map<Integer, String> newLineNumMapItem = new HashMap<>();// use for delete blank and comment
                                                             // item
    int lineCounter = 1;
    for (String newItem : newItems) {
      newItem = newItem.trim();
      newLineNumMapItem.put(lineCounter, newItem);

      // comment item
      if (isCommentItem(newItem)) {
        ItemDTO oldItemDTO = null;
        if (!CollectionUtils.isEmpty(baseCommentItems)) {
          oldItemDTO = baseCommentItems.remove(0);
        }

View on GitHub (pinned to d95fc18d11)

Solutions

  1. Remove or rename the duplicate key(s) listed in the error message before saving.
  2. Remember the comparison is case-insensitive (key and KEY collide).
  3. Use the repeated-keys validation client-side (see validationCode) to catch it before submit.
  4. Keep comment lines (starting with #) and blank lines out of the duplication check; they are ignored.

Example fix

// before
timeout=10
TIMEOUT=20   // collides (case-insensitive)

// after
timeout=10
connect.timeout=20
Defensive patterns

Strategy: validation

Validate before calling

// Validate config text client-side exactly like PropertyResolver: case-insensitive keys,
// comment lines start with '#', blank lines ignored.
Set<String> findRepeatedKeys(String configText) {
  Set<String> seen = new HashSet<>();
  Set<String> dups = new HashSet<>();
  for (String raw : configText.split("\\r?\\n")) {
    String line = raw.trim();
    if (line.isEmpty() || line.startsWith("#")) continue;
    int eq = line.indexOf('=');
    if (eq < 0) continue; // handled by error 143/144
    String key = line.substring(0, eq).trim().toLowerCase(Locale.ROOT);
    if (!seen.add(key)) dups.add(key);
  }
  return dups;
}
// assert findRepeatedKeys(text).isEmpty() before POST

Prevention

When it happens

Trigger: POSTing or saving namespace item text (the textarea config-text save flow) where two non-comment, non-blank lines define the same property key (case-insensitive).

Common situations: Copy-pasting a block that already contained the key; merging two property files; keys that differ only by case (Foo / foo) which the resolver folds together.

Related errors


AI-assisted analysis of apolloconfig/apollo@d95fc18d11 (2026-08-14). Data as JSON: /api/errors/c9a0783242c64b00. Report an issue: GitHub.