apache/beam · error

Invalid underlying type

Error message

Invalid underlying type: %v

What it means

typex.New's outer switch expects the type's Class() to be either Composite or Singleton (the leaf case). Any other class value reaches the default branch and panics with 'Invalid underlying type'. This is a last-resort invariant check that FullType trees are built only from these two classes.

Solutions

  1. Build types via the provided helpers (typex.New, typex.NewKV, etc.) rather than constructing raw class values.
  2. Verify the FullType being passed was produced by this SDK version; regenerate or update code that hardcodes class values.
  3. Align SDK versions across modules to eliminate unknown class encodings.
Defensive patterns

Strategy: validation

Validate before calling

func validClass(t typex.Type) bool {
    c := t.Class()
    return c == typex.Composite || c == typex.Singleton
}

Try / catch

func safeNew(t typex.Type, cs ...typex.FullType) (ft typex.FullType, err error) {
    defer func() {
        if r := recover(); r != nil { err = fmt.Errorf("typex.New: %v", r) }
    }()
    return typex.New(t, cs...), nil
}

Prevention

When it happens

Trigger: Calling typex.New with a type whose Class() is neither Composite nor Singleton — for example a raw/undetermined class, or a mis-constructed typex.Type. Reached via the public New and its callers (Prefix, CoGroupByKey, CombinePerKey, CombineGlobally, Flatten, GroupByKey).

Common situations: Programmatically assembling types from constants and hitting an invalid class value; version skew where a type carries a class value this SDK version does not understand; typos when building types in generated code.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/core/typex/fulltype.go:163

			if isAnyNonKVComposite(components) {
				panic(fmt.Sprintf("Invalid to nest composites inside CoGBK: %v", t))
			}
			return &tree{class, t, components}
		case TimersType:
			return &tree{class, t, components}
		case ShardedKeyType:
			if len(components) != 1 {
				panic(fmt.Sprintf("Invalid number of components for ShardedKey: %v, %v", t, components))
			}
			if components[0].Class() == Composite {
				panic(fmt.Sprintf("Invalid to nest composite inside ShardedKey: %v, %v", t, components))
			}
			return &tree{class, t, components}
		default:
			panic(fmt.Sprintf("Unexpected composite type: %v", t))
		}
	default:
		panic(fmt.Sprintf("Invalid underlying type: %v", t))
	}
}

// NOTE(herohde) 1/26/2018: we allow nested KV types and coders to support the
// CoGBK translation (using KV<K,KV<int,[]byte>> to encode keyed raw union values)
// and potentially other uses. We do not have a reasonable way to emit nested KV
// values, so user functions are still limited to non-nested KVs. Universally-typed
// KV-values might be simple to allow, for example.

func isAnyNonKVComposite(list []FullType) bool {
	for _, t := range list {
		if t.Class() == Composite && t.Type() != KVType {
			return true
		}
	}
	return false
}

View on GitHub (pinned to 12126d8942)