{"id":"3af41aa39f626f0b","repo":"apache/kafka","slug":"unknown-sensor-name","errorCode":null,"errorMessage":"Unknown sensor {name}","messagePattern":"Unknown sensor (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/common/metrics/internals/PluginMetricsImpl.java","lineNumber":99,"sourceCode":"    @Override\n    public Sensor addSensor(String name) {\n        if (closing) throw new IllegalStateException(\"This PluginMetrics instance is closed\");\n        if (sensors.contains(name)) {\n            throw new IllegalArgumentException(\"Sensor \" + name + \" already exists\");\n        }\n        Sensor sensor = metrics.sensor(name);\n        sensors.add(name);\n        return sensor;\n    }\n\n    @Override\n    public void removeSensor(String name) {\n        if (closing) throw new IllegalStateException(\"This PluginMetrics instance is closed\");\n        if (sensors.contains(name)) {\n            metrics.removeSensor(name);\n            sensors.remove(name);\n        } else {\n            throw new IllegalArgumentException(\"Unknown sensor \" + name);\n        }\n    }\n\n    @Override\n    public void close() throws IOException {\n        closing = true;\n        for (String sensor : sensors) {\n            metrics.removeSensor(sensor);\n        }\n        for (MetricName metricName : metricNames) {\n            metrics.removeMetric(metricName);\n        }\n    }\n}\n","sourceCodeStart":81,"sourceCodeEnd":114,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/common/metrics/internals/PluginMetricsImpl.java#L81-L114","documentation":"Thrown by PluginMetricsImpl.removeSensor when the supplied name is not in the handle's 'sensors' set — the sensor was either never added through this handle, was added through the raw Metrics object, or has already been removed. The handle enforces a strict add-before-remove contract: only sensors it created can be removed through it.","triggerScenarios":"Calling pluginMetrics.removeSensor(name) for a sensor created via metrics.sensor(name) directly, created via a different PluginMetrics instance, or removed earlier. Also occurs when the name string differs in case or whitespace from the one passed to addSensor.","commonSituations":"Migrating a plugin to PluginMetrics but still creating some sensors with the legacy metrics.sensor() API; double-cleanup paths; plugins sharing state across instances where one instance tries to remove a sensor owned by another.","solutions":["Only remove sensors you added via pluginMetrics.addSensor(name) on the same handle; track added names in a Set if you remove them selectively.","If you created the sensor via metrics.sensor(name), remove it via metrics.removeSensor(name) instead.","Guard removeSensor calls (or let PluginMetrics.close() do the cleanup) to avoid removing sensors you do not own."],"exampleFix":"// before\nSensor s = metrics.sensor(\"x\");                 // raw Metrics\n...\npluginMetrics.removeSensor(\"x\");                // Unknown sensor\n// after\nSensor s = pluginMetrics.addSensor(\"x\");        // PluginMetrics handle\n...\npluginMetrics.removeSensor(\"x\");                // ok","handlingStrategy":"validation","validationCode":"// Track sensors you created; only remove what you own.\nprivate final Set<String> registeredSensors = ConcurrentHashMap.newKeySet();\nif (name == null || !registeredSensors.remove(name)) {\n    return; // not created by this plugin\n}\npluginMetrics.removeSensor(name);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep your own registry of created sensor names and only call removeSensor for names you successfully added.","Make removeSensor idempotent: check your own set first.","Never reuse a PluginMetrics instance to manage sensors created through the underlying Metrics object directly — they won't be tracked here."],"tags":["metrics","plugin-lifecycle","api-misuse"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}