{"record":{"id":"c9a0783242c64b00","repo":"apolloconfig/apollo","slug":"config-text-has-repeated-keys-s-please-check-yo","errorCode":null,"errorMessage":"Config text has repeated keys: %s, please check your input.","messagePattern":"Config text has repeated keys: (.+?), please check your input\\.","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"warning","filePath":"apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/txtresolver/PropertyResolver.java","lineNumber":75,"sourceCode":"    // comment items\n    List<ItemDTO> baseCommentItems = new LinkedList<>();\n    // blank items\n    List<ItemDTO> baseBlankItems = new LinkedList<>();\n    if (!CollectionUtils.isEmpty(baseItems)) {\n\n      baseCommentItems = baseItems.stream().filter(this::isCommentItem)\n          .sorted(Comparator.comparing(ItemDTO::getLineNum))\n          .collect(Collectors.toCollection(LinkedList::new));\n\n      baseBlankItems = baseItems.stream().filter(this::isBlankItem)\n          .sorted(Comparator.comparing(ItemDTO::getLineNum))\n          .collect(Collectors.toCollection(LinkedList::new));\n    }\n\n    String[] newItems = configText.split(ITEM_SEPARATOR);\n    Set<String> repeatKeys = new HashSet<>();\n    if (isHasRepeatKey(newItems, repeatKeys)) {\n      throw new BadRequestException(\"Config text has repeated keys: %s, please check your input.\",\n          repeatKeys);\n    }\n\n    ItemChangeSets changeSets = new ItemChangeSets();\n    Map<Integer, String> newLineNumMapItem = new HashMap<>();// use for delete blank and comment\n                                                             // item\n    int lineCounter = 1;\n    for (String newItem : newItems) {\n      newItem = newItem.trim();\n      newLineNumMapItem.put(lineCounter, newItem);\n\n      // comment item\n      if (isCommentItem(newItem)) {\n        ItemDTO oldItemDTO = null;\n        if (!CollectionUtils.isEmpty(baseCommentItems)) {\n          oldItemDTO = baseCommentItems.remove(0);\n        }\n","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/apolloconfig/apollo/blob/d95fc18d112589efc09ddcbe1507047584d55251/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/txtresolver/PropertyResolver.java#L57-L93","documentation":"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]).","triggerScenarios":"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).","commonSituations":"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.","solutions":["Remove or rename the duplicate key(s) listed in the error message before saving.","Remember the comparison is case-insensitive (key and KEY collide).","Use the repeated-keys validation client-side (see validationCode) to catch it before submit.","Keep comment lines (starting with #) and blank lines out of the duplication check; they are ignored."],"exampleFix":"// before\ntimeout=10\nTIMEOUT=20   // collides (case-insensitive)\n\n// after\ntimeout=10\nconnect.timeout=20","handlingStrategy":"validation","validationCode":"// Validate config text client-side exactly like PropertyResolver: case-insensitive keys,\n// comment lines start with '#', blank lines ignored.\nSet<String> findRepeatedKeys(String configText) {\n  Set<String> seen = new HashSet<>();\n  Set<String> dups = new HashSet<>();\n  for (String raw : configText.split(\"\\\\r?\\\\n\")) {\n    String line = raw.trim();\n    if (line.isEmpty() || line.startsWith(\"#\")) continue;\n    int eq = line.indexOf('=');\n    if (eq < 0) continue; // handled by error 143/144\n    String key = line.substring(0, eq).trim().toLowerCase(Locale.ROOT);\n    if (!seen.add(key)) dups.add(key);\n  }\n  return dups;\n}\n// assert findRepeatedKeys(text).isEmpty() before POST","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run the duplicate-key check above before every save.","Remember keys are compared case-insensitively.","Normalize your config tooling to lowercase keys consistently.","Exclude comment/blank lines from the check."],"tags":["config","validation","properties","namespace","bad-request"],"backgroundTag":null,"analyzedSha":"d95fc18d112589efc09ddcbe1507047584d55251","analyzedAt":"2026-08-14T04:00:05.477Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}