{"record":{"id":"82dc5dce44a0c096","repo":"nathanmarz/storm","slug":"meanreducer-reduce-called-with-unsupported-input-type-input","errorCode":null,"errorMessage":"MeanReducer::reduce called with unsupported input type `${input.getClass()}`. Supported types are Double, Long, Integer.","messagePattern":"MeanReducer::reduce called with unsupported input type `(.+?)`\\. Supported types are Double, Long, Integer\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"storm-core/src/jvm/backtype/storm/metric/api/MeanReducer.java","lineNumber":41,"sourceCode":"    public int count = 0;\n    public double sum = 0.0;\n}\n\npublic class MeanReducer implements IReducer<MeanReducerState> {\n    public MeanReducerState init() {\n        return new MeanReducerState();\n    }\n\n    public MeanReducerState reduce(MeanReducerState acc, Object input) {\n        acc.count++;\n        if(input instanceof Double) {\n            acc.sum += (Double)input;\n        } else if(input instanceof Long) {\n            acc.sum += ((Long)input).doubleValue();\n        } else if(input instanceof Integer) {\n            acc.sum += ((Integer)input).doubleValue();\n        } else {\n            throw new RuntimeException(\n                \"MeanReducer::reduce called with unsupported input type `\" + input.getClass()\n                + \"`. Supported types are Double, Long, Integer.\");\n        }\n        return acc;\n    }\n\n    public Object extractResult(MeanReducerState acc) {\n        if(acc.count > 0) {\n            return new Double(acc.sum / (double)acc.count);\n        } else {\n            return null;\n        }\n    }\n}\n","sourceCodeStart":23,"sourceCodeEnd":56,"githubUrl":"https://github.com/nathanmarz/storm/blob/cdb116e942666973bc4eaa0df098d5bab82739e7/storm-core/src/jvm/backtype/storm/metric/api/MeanReducer.java#L23-L56","documentation":"MeanReducer averages incoming metric values but only understands Double, Long, and Integer inputs. If reduce receives any other object type (e.g. String, a custom Number, or a complex value emitted by a metric), it cannot add it to the running sum, so it throws with the offending class name in the message.","triggerScenarios":"Registering a MeanReducer as the reducer for a metric whose emitted values are not Double/Long/Integer — e.g. reducedMetrics registered with MeanReducer while the metric produces String or a custom object.","commonSituations":"Wiring MeanReducer to a metric that emits Strings or booleans; a custom IMetric implementation returning non-numeric objects; a metric's emitted type changed after a refactor while the reducer stayed the same.","solutions":["Make the metric emit numeric values (Double, Long, or Integer) — convert Strings/booleans before returning from the IMetric.","If values are non-numeric by design, use a different reducer (or write a custom IReducer) that supports the actual type.","Inspect the message's input type name to find which metric emits the offending type and fix that metric's getValue return type.","If longs are wanted as double, have the metric emit Long/Double explicitly instead of custom Number subclasses."],"exampleFix":"// before\npublic Object getValueAndReset() { return Long.toString(count); } // emits String\n// after\npublic Object getValueAndReset() { return count; } // emits Long, accepted by MeanReducer","handlingStrategy":"type-guard","validationCode":"Object v = metric.getValueAndReset();\nif (!(v instanceof Double || v instanceof Long || v instanceof Integer)) {\n    throw new IllegalStateException(\"MeanReducer metric must emit Double/Long/Integer, got \" + v.getClass());\n}","typeGuard":"boolean isMeanReducerInput(Object v) {\n    return v instanceof Double || v instanceof Long || v instanceof Integer;\n}","tryCatchPattern":"try {\n    reducedStream.meanReduce(value);\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"MeanReducer::reduce\")) {\n        // metric emitted a non-numeric type; fix the metric's getValueAndReset return type\n    } else throw e;\n}","preventionTips":["Have every IMetric return a boxed numeric type (Long/Double) from getValueAndReset.","Pair MeanReducer only with metrics documented as numeric.","Write a unit test invoking MeanReducer.reduce with your metric's emitted value.","Convert boolean/count-like metrics to Long before emitting."],"tags":["metrics","type-mismatch","reducer","storm"],"backgroundTag":"type-mismatch","analyzedSha":"cdb116e942666973bc4eaa0df098d5bab82739e7","analyzedAt":"2026-09-12T14:30:00.714Z","contentChangedAt":"2026-09-12T14:30:00.714Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}