{"id":"f3c37dd2e2843da0","repo":"apache/kafka","slug":"not-a-measurable-metricvalueproviderclass","errorCode":null,"errorMessage":"Not a measurable: {metricValueProviderClass}","messagePattern":"Not a measurable: (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/common/metrics/KafkaMetric.java","lineNumber":104,"sourceCode":"    /**\n     * The method determines if the metric value provider is of type Measurable.\n     *\n     * @return true if the metric value provider is of type Measurable, false otherwise.\n     */\n    public boolean isMeasurable() {\n        return this.metricValueProvider instanceof Measurable;\n    }\n\n    /**\n     * Get the underlying metric provider, which should be a {@link Measurable}\n     * @return Return the metric provider\n     * @throws IllegalStateException if the underlying metric is not a {@link Measurable}.\n     */\n    public Measurable measurable() {\n        if (isMeasurable())\n            return (Measurable) metricValueProvider;\n        else\n            throw new IllegalStateException(\"Not a measurable: \" + this.metricValueProvider.getClass());\n    }\n\n    /**\n     * Take the metric and return the value, where the underlying metric provider should be a {@link Measurable}\n     * @param timeMs The time that this metric is taken\n     * @return Return the metric value if it's measurable, otherwise 0\n     */\n    double measurableValue(long timeMs) {\n        synchronized (this.lock) {\n            if (isMeasurable())\n                return ((Measurable) metricValueProvider).measure(config, timeMs);\n            else\n                return 0;\n        }\n    }\n\n    /**\n     * Set the metric config.","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/common/metrics/KafkaMetric.java#L86-L122","documentation":"Thrown by KafkaMetric.measurable() when the underlying metricValueProvider does not implement the Measurable interface. Kafka metrics are backed either by a Measurable (a synchronous function of config+time, e.g. Avg/Max/Rate) or by a Gauge-style MetricValueProvider whose value is supplied on demand. measurable() is only valid for the former; callers that need a numeric snapshot of either kind should use measurableValue(timeMs) or metricValue() instead.","triggerScenarios":"Code holds a KafkaMetric reference and calls measurable() on one whose provider was registered via Metrics.addMetric(name, (MetricValueProvider<?>) gaugeLikeProvider). Because the provider is not Measurable, KafkaMetric.measurable() at line 104 throws IllegalStateException naming the actual provider class.","commonSituations":"Custom MetricValueProvider implementations (Gauges wrapping external state) being inspected by tooling that assumes every metric is measurable. Reporters or tests iterating over Metrics.metrics().values() and calling measurable() without first checking isMeasurable(). Version upgrades where a metric previously implemented Measurable and was refactored to a generic provider.","solutions":["Guard the call: if (kafkaMetric.isMeasurable()) kafkaMetric.measurable(); else ... handle the gauge path.","Prefer kafkaMetric.measurableValue(timeMs) which returns 0 for non-measurable metrics, or metricValue() for the provider's current value.","If your custom provider should be measurable, implement org.apache.kafka.common.metrics.Measurable rather than just MetricValueProvider."],"exampleFix":"// before: Measurable m = kafkaMetric.measurable();\n// after:\nif (kafkaMetric.isMeasurable()) {\n    Measurable m = kafkaMetric.measurable();\n} else {\n    double v = kafkaMetric.measurableValue(System.currentTimeMillis());\n}","handlingStrategy":"type-guard","validationCode":"// Guard with the public isMeasurable() check before calling measurable().\nif (kafkaMetric.isMeasurable()) {\n    Measurable m = kafkaMetric.measurable();\n    double v = m.measure(config, System.currentTimeMillis());\n} else {\n    // provider is a non-Measurable MetricValueProvider (e.g., gauge); use value() instead.\n}","typeGuard":"// Narrow to Measurable before invoking measurable().\nif (!(metricValueProvider instanceof Measurable)) {\n    // cannot call measurable(); use measurableValue() which returns 0 for non-measurables.\n}\nboolean isMeasurable(KafkaMetric km) { return km != null && km.isMeasurable(); }","tryCatchPattern":"try {\n    Measurable m = kafkaMetric.measurable();\n} catch (IllegalStateException e) {\n    // provider is not Measurable; fall back to measurableValue(timeMs) or skip.\n}","preventionTips":["Always call isMeasurable() before measurable() — it is the documented guard.","Remember Gauge / non-Measurable providers are valid; they just don't support measure().","Prefer KafkaMetric.measurableValue(timeMs) when you only need a numeric value and tolerate 0 for non-measurables.","When adding metrics, decide upfront whether you need a Measurable or a Gauge."],"tags":["metrics","measurable","gauge","api-misuse"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}