{"record":{"id":"04f2616d2296718a","repo":"apache/seatunnel","slug":"unsupported-metric-class-metricclass","errorCode":null,"errorMessage":"Unsupported metric class: ${metricClass}","messagePattern":"Unsupported metric class: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/metrics/ConnectorMetricsCalcContext.java","lineNumber":334,"sourceCode":"        } else {\n            String metricName =\n                    PluginType.SINK.equals(type)\n                            ? sinkMetric + \"#\" + tableName\n                            : sourceMetric + \"#\" + tableName;\n            T newMetric = createMetric(metricsContext, metricName, cls);\n            processor.process(newMetric);\n            metricMap.put(tableName, newMetric);\n        }\n    }\n\n    private <T> T createMetric(\n            MetricsContext metricsContext, String metricName, Class<T> metricClass) {\n        if (metricClass == Counter.class) {\n            return metricClass.cast(metricsContext.counter(metricName));\n        } else if (metricClass == Meter.class) {\n            return metricClass.cast(metricsContext.meter(metricName));\n        }\n        throw new IllegalArgumentException(\"Unsupported metric class: \" + metricClass.getName());\n    }\n\n    @FunctionalInterface\n    interface MetricProcessor<T> {\n        void process(T t);\n    }\n\n    private static final class PendingMetrics {\n        private long count;\n        private long bytes;\n        private final Map<String, TablePendingMetrics> tableMetrics = new ConcurrentHashMap<>();\n\n        void add(String tableName, long rowBytes) {\n            count++;\n            bytes += rowBytes;\n            if (StringUtils.isNotBlank(tableName)) {\n                tableMetrics\n                        .computeIfAbsent(tableName, key -> new TablePendingMetrics())","sourceCodeStart":316,"sourceCodeEnd":352,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/metrics/ConnectorMetricsCalcContext.java#L316-L352","documentation":"ConnectorMetricsCalcContext.createMetric instantiates a metric from a MetricsContext by class: only Counter and Meter are supported. If a connector declares a metric of another class (e.g. Gauge, Histogram, DistributionSummary), IllegalArgumentException 'Unsupported metric class' is thrown when the metric is created via newMetric.","triggerScenarios":"A Source/Sink/Transform declares a metric via @Metric with a getMetric() returning a type other than Counter or Meter, and the metrics system calls newMetric -> createMetric for that connector metric during job metric initialization.","commonSituations":"Custom connector exposing a Gauge or Histogram metric; connector code updated to a new metric type not yet supported by the engine's metrics bridge; generic helper returning Object cast to an unsupported Class<T>.","solutions":["Change the connector metric to a supported type: Counter for counts, Meter for rates.","If you need gauge-like values, model them as a Counter updated by the connector.","Check the SeaTunnel version - newer metric types may require upgrading the engine.","Fix any generic metric factory code that passes unexpected Class<T> values into createMetric."],"exampleFix":"// before\n@Metric\nGauge<Double> queueSize();\n// after\n@Metric\nCounter enqueuedCount();","handlingStrategy":"validation","validationCode":"Class<?> c = metric.getMetric().getClass();\nif (c != Counter.class && c != Meter.class) {\n    throw new IllegalArgumentException(\"connector metric must be Counter or Meter: \" + c.getName());\n}","typeGuard":"static boolean isSupportedMetric(Object m) {\n    return m instanceof Counter || m instanceof Meter;\n}","tryCatchPattern":"try {\n    MetricsContext.register(connectorMetrics);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Unsupported metric class\")) {\n        log.warn(\"skipping unsupported metric: {}\", e.getMessage());\n    } else throw e;\n}","preventionTips":["Declare connector metrics only as Counter or Meter.","Write a unit test that instantiates every @Metric in your connector.","Pin connector builds to the same SeaTunnel API version as the engine."],"tags":["metrics","connector","unsupported-type"],"backgroundTag":"unsupported-enum-value","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}