apache/beam · error

Unexpected number type

Error message

Unexpected number type: %v

What it means

In Apache Beam Go SDK's stats package, maxPerKey/Mean-like helpers dispatch to a numeric-specific max function via a generated switch on reflect.Type. If the requested type does not correspond to any generated instantiation (int, int8..., float64, etc.), the default branch panics. This is a defensive check that the API was only called for supported numeric types.

Solutions

  1. Ensure the input PCollection elements are one of the supported numeric types (ints, uints, float32/float64 as generated in the template).
  2. Pre-map the PCollection to a supported numeric type with beam.Map before applying stats.Max.
  3. Check for type alias/defined-type mismatches and convert with explicit casts.
  4. If a legit numeric type is missing, regenerate templates or extend the stats package's X list for that type.

Example fix

// before
words := beam.ParDo(s, func(w string) string { return w }, in)
stats.Max(s, words) // panics: string

// after
lens := beam.Map(s, func(w string) int { return len(w) }, in)
stats.Max(s, lens)
Defensive patterns

Strategy: validation

Validate before calling

// Guard: only call stats.Max on supported numeric element types
func maxSupported(c beam.PCollection) bool {
    switch c.Type().String() {
    case "int", "int8", "int16", "int32", "int64",
        "uint", "uint8", "uint16", "uint32", "uint64",
        "float32", "float64":
        return true
    }
    return false
}

Type guard

func isNumericForStats(v any) bool {
    switch reflect.ValueOf(v).Kind() {
    case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
        reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
        reflect.Float32, reflect.Float64:
        return true
    }
    return false
}

Try / catch

// Beam panics abort the pipeline; validate eagerly instead.
// If you must catch:
func safeMax(s beam.Scope, col beam.PCollection) (ret beam.PCollection) {
    defer func() {
        if r := recover(); r != nil {
            log.Printf("stats.Max failed: %v", r)
            ret = nil
        }
    }()
    return stats.Max(s, col)
}

Prevention

When it happens

Trigger: Calling stats.Max (or the MaxPerKey/Max switch dispatcher) with a PCollection whose element type is not one of the generated numeric types — e.g. a struct, string, interface, uint64 on some builds, or an unnamed/aliased type whose reflect.String() doesn't match the case list.

Common situations: Feeding stats.Max a PCollection of strings or custom types, using type aliases that produce unexpected reflect type strings, or pipeline reshaping that loses the concrete numeric type (element type becomes interface{}).

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/2d58c6d2ce3d53f2. Report an issue: GitHub.

Appendix: source

Thrown at sdks/go/pkg/beam/transforms/stats/max_switch.tmpl:30

// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package stats

import (
    "fmt"
    "reflect"
)

func findMaxFn(t reflect.Type) any {
    switch t.String() {
{{- range .X}}
    case "{{.Type}}":
		return max{{.Name}}Fn
{{- end}}
	default:
		panic(fmt.Sprintf("Unexpected number type: %v", t))
	}
}
{{range .X}}
func max{{.Name}}Fn(x, y {{.Type}}) {{.Type}} {
	if x > y {
		return x
	}
	return y
}
{{end}}

View on GitHub (pinned to 12126d8942)