apache/beam · error

couldn't decode characteristic for variant

Error message

couldn't decode characteristic for variant %v handler %v: %v

What it means

When reading a characteristic value for a runner variant+handler, config.go decodes the YAML node into the characteristic's Go type via reflection. The decode is expected to succeed because the config was pre-validated, so failure triggers a panic indicating the validated config and the decode path have diverged (an internal invariant break).

Solutions

  1. Check the variant/handler YAML content against the expected characteristic schema
  2. Regenerate or simplify the config file to the documented format
  3. Verify the handler key exists with a compatible value type (string vs struct, etc.)
  4. File a bug with the config file if pre-validation passes but decode fails

Example fix

// before: mismatched yaml value type
variant:
  handler: 123
// after
variant:
  handler: "valid-string-value"
Defensive patterns

Strategy: validation

Validate before calling

// validate config against the schema before load
if err := config.Validate(yamlBytes); err != nil { return fmt.Errorf("invalid characteristic config: %w", err) }

Try / catch

// GetCharacteristics panics by design; guard the loader
defer func() { if r := recover(); r != nil { err = fmt.Errorf("characteristic decode failed: %v", r) } }()

Prevention

When it happens

Trigger: GetCharacteristics is called with a handler key present in the variant's handlers map, but yn.Decode fails — e.g. the yaml.Node's shape doesn't match the characteristic's Go type, or KnownFields(true)-style strictness rejects content the pre-validation passed.

Common situations: Hand-edited or programmatically generated config YAML whose node structure mismatches the ConfigCharacteristic type; running a custom variant config; a bug where validation and decode use different type mappings.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/runners/prism/internal/config/config.go:142

func (v *Variant) GetCharacteristics(handler string) any {
	if v == nil {
		return nil
	}
	md, ok := v.parent.metadata[handler]
	if !ok {
		return nil
	}
	rt := md.ConfigCharacteristic()

	// Get a pointer to the concrete value.
	rtv := reflect.New(rt)

	// look up the handler urn in the variant.
	yn := v.handlers[handler]
	//
	if err := yn.Decode(rtv.Interface()); err != nil {
		// We prevalidated the config, so this shouldn't happen.
		panic(fmt.Sprintf("couldn't decode characteristic for variant %v handler %v: %v", v.name, handler, err))
	}

	// Return the value pointed to by the pointer.
	return rtv.Elem().Interface()
}

// HandlerRegistry stores known handlers and their associated metadata needed to parse
// the YAML configuration.
type HandlerRegistry struct {
	variations map[string]*rawVariant
	metadata   map[string]HandlerMetadata

	// cached names
	variantIDs, handerIDs []string
}

// NewHandlerRegistry creates an initialized HandlerRegistry.
func NewHandlerRegistry() *HandlerRegistry {

View on GitHub (pinned to 12126d8942)