{"record":{"id":"304e36fc5c05bad8","repo":"apache/beam","slug":"expected-float64-got-data-of-type-t-instead","errorCode":null,"errorMessage":"expected float64, got data of type %T instead","messagePattern":"expected float64, got data of type %T instead","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/runners/dataflow/dataflowlib/metrics.go","lineNumber":101,"sourceCode":"\t\t\tbreak\n\t\t}\n\t}\n\tif userStepName == \"\" {\n\t\treturn metrics.StepKey{}, fmt.Errorf(\"could not translate the internal step name %v\", stepName)\n\t}\n\n\tnamespace := metric.Name.Context[\"namespace\"]\n\tif namespace == \"\" {\n\t\tnamespace = \"dataflow/v1b3\"\n\t}\n\n\treturn metrics.StepKey{Step: userStepName, Name: metric.Name.Name, Namespace: namespace}, nil\n}\n\nfunc extractCounterValue(obj any) (int64, error) {\n\tv, ok := obj.(float64)\n\tif !ok {\n\t\treturn -1, fmt.Errorf(\"expected float64, got data of type %T instead\", obj)\n\t}\n\treturn int64(v), nil\n}\n\nfunc extractDistributionValue(obj any) (metrics.DistributionValue, error) {\n\tm := obj.(map[string]any)\n\tpropertiesToVisit := []string{\"count\", \"sum\", \"min\", \"max\"}\n\tvar values [4]int64\n\n\tfor i, p := range propertiesToVisit {\n\t\tv, ok := m[p].(float64)\n\t\tif !ok {\n\t\t\treturn metrics.DistributionValue{}, fmt.Errorf(\"expected float64, got data of type %T instead\", m[p])\n\t\t}\n\t\tvalues[i] = int64(v)\n\t}\n\treturn metrics.DistributionValue{Count: values[0], Sum: values[1], Min: values[2], Max: values[3]}, nil\n}","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/runners/dataflow/dataflowlib/metrics.go#L83-L119","documentation":"Dataflow counter metric values arrive as generic decoded JSON, and extractCounterValue asserts they are float64 before converting to int64. This error means the counter's scalar value had a different Go type (string, nil, nested object, etc.), so it cannot be interpreted as a numeric counter.","triggerScenarios":"groupByType calls extractCounterValue on a MetricUpdate value that is not a JSON number — e.g. a counter whose value is null (no updates), a string-encoded number, or a distributed-metric payload routed to the counter path.","commonSituations":"Counters reported with no value yet (null) in early job stages; Dataflow API returning values with unexpected shapes; misrouted distribution updates handled by the counter extractor.","solutions":["Handle JSON null/missing values before calling extractCounterValue and default to 0 or skip","Check whether the metric is a distribution and route it to extractDistributionValue instead","Guard with a type assertion and log the raw %T payload for debugging"],"exampleFix":"// before\nval, err := extractCounterValue(raw)\n// after\nif raw == nil {\n    raw = float64(0)\n}\nval, err := extractCounterValue(raw)","handlingStrategy":"type-guard","validationCode":"if v, ok := raw.(float64); !ok {\n    log.Printf(\"counter %v: non-numeric value %T, skipping\", name, raw)\n    return\n}","typeGuard":"func isCounterValue(obj any) (int64, bool) {\n    v, ok := obj.(float64)\n    return int64(v), ok\n}","tryCatchPattern":"val, err := extractCounterValue(raw)\nif err != nil {\n    log.Printf(\"bad counter value: %v\", err)\n    continue\n}","preventionTips":["Default nil counter values to 0 before extraction","Route metrics by kind (counter vs distribution) before extraction","Log %T of unexpected payloads to catch Dataflow API shape changes early"],"tags":["dataflow","go","metrics","type-assertion"],"backgroundTag":"type-mismatch","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}