{"record":{"id":"429501c06f8f6ec4","repo":"elastic/elasticsearch","slug":"repeated-attribute-key","errorCode":null,"errorMessage":"repeated attribute key [{}]","messagePattern":"repeated attribute key \\[(.+?)\\]","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"warning","filePath":"client/sniffer/src/main/java/org/elasticsearch/client/sniff/ElasticsearchNodesSniffer.java","lineNumber":197,"sourceCode":"                            }\n                            publishedHost = new HttpHost(host, publishAddressAsURI.getPort(), publishAddressAsURI.getScheme());\n                        } else if (parser.currentToken() == JsonToken.START_ARRAY && \"bound_address\".equals(parser.getCurrentName())) {\n                            while (parser.nextToken() != JsonToken.END_ARRAY) {\n                                URI boundAddressAsURI = URI.create(scheme + \"://\" + parser.getValueAsString());\n                                boundHosts.add(\n                                    new HttpHost(boundAddressAsURI.getHost(), boundAddressAsURI.getPort(), boundAddressAsURI.getScheme())\n                                );\n                            }\n                        } else if (parser.getCurrentToken() == JsonToken.START_OBJECT) {\n                            parser.skipChildren();\n                        }\n                    }\n                } else if (\"attributes\".equals(fieldName)) {\n                    while (parser.nextToken() != JsonToken.END_OBJECT) {\n                        if (parser.getCurrentToken() == JsonToken.VALUE_STRING) {\n                            String oldValue = protoAttributes.put(parser.getCurrentName(), parser.getValueAsString());\n                            if (oldValue != null) {\n                                throw new IOException(\"repeated attribute key [\" + parser.getCurrentName() + \"]\");\n                            }\n                        } else {\n                            parser.skipChildren();\n                        }\n                    }\n                } else {\n                    parser.skipChildren();\n                }\n            } else if (parser.currentToken() == JsonToken.START_ARRAY) {\n                if (\"roles\".equals(fieldName)) {\n                    sawRoles = true;\n                    while (parser.nextToken() != JsonToken.END_ARRAY) {\n                        roles.add(parser.getText());\n                    }\n                } else {\n                    parser.skipChildren();\n                }\n            } else if (parser.currentToken().isScalarValue()) {","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/client/sniffer/src/main/java/org/elasticsearch/client/sniff/ElasticsearchNodesSniffer.java#L179-L215","documentation":"Thrown while reading a node's 'attributes' object: each attribute key may appear at most once. If the same key is seen twice, the parser aborts with IOException because duplicate attributes would make node role/attribute decisions ambiguous.","triggerScenarios":"The ES nodes-info response contains a node whose attributes object lists the same key twice. Usually a sign of a malformed server response or a non-standard node-attributes source.","commonSituations":"Sniffing against a non-conformant or older/patched ES build that emits duplicate attribute keys; a proxy that merged attributes incorrectly; custom node attributes plugin producing duplicates.","solutions":["Inspect the offending node's attributes via GET _nodes/_local/node_attrs to find the duplicate key.","Fix the source of the duplicated attribute (elasticsearch.yml node.attr settings, or the plugin emitting it).","If you cannot change the server, run the sniffer against a fixed node list instead of the nodes-info API."],"exampleFix":"// before (elasticsearch.yml on node)\nnode.attr.rack: r1\nnode.attr.rack: r2   // duplicate key -> sniffer fails\n// after\nnode.attr.rack: r1\nnode.attr.zone: z2  // distinct keys","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { sniffer.sniff(); }\ncatch (IOException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"repeated attribute key\")) {\n        // inspect _nodes node attributes; fall back to static node list\n    } else throw e;\n}","preventionTips":["Audit node.attr.* settings for accidental duplicates.","Sniff fixed hosts if the server response is outside your control."],"tags":["sniffer","parsing","json","node-attributes"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}