henrygd/beszel · error

unexpected dest type for GetData: %T

Error message

unexpected dest type for GetData: %T

What it means

For legacy (0.18.x) responses without a generic Data field, unmarshalLegacyResponse type-asserts dest to *system.CombinedData when action is common.GetData; a mismatched pointer yields 'unexpected dest type for GetData: %T'. It is a programming-error guard ensuring the typed legacy field is only copied into the correct destination.

Source

Thrown at internal/hub/transport/transport.go:53

	}
	// Try generic Data field first (0.19+)
	if len(resp.Data) > 0 {
		if err := cbor.Unmarshal(resp.Data, dest); err != nil {
			return fmt.Errorf("failed to unmarshal generic response data: %w", err)
		}
		return nil
	}
	// Fall back to legacy typed fields for older agents/hubs.
	return unmarshalLegacyResponse(resp, action, dest)
}

// unmarshalLegacyResponse handles legacy responses that use typed fields.
func unmarshalLegacyResponse(resp common.AgentResponse, action common.WebSocketAction, dest any) error {
	switch action {
	case common.GetData:
		d, ok := dest.(*system.CombinedData)
		if !ok {
			return fmt.Errorf("unexpected dest type for GetData: %T", dest)
		}
		if resp.SystemData == nil {
			return errors.New("no system data in response")
		}
		*d = *resp.SystemData
		return nil
	case common.CheckFingerprint:
		d, ok := dest.(*common.FingerprintResponse)
		if !ok {
			return fmt.Errorf("unexpected dest type for CheckFingerprint: %T", dest)
		}
		if resp.Fingerprint == nil {
			return errors.New("no fingerprint in response")
		}
		*d = *resp.Fingerprint
		return nil
	case common.GetContainerLogs:
		d, ok := dest.(*string)

View on GitHub (pinned to b38fb7dafa)

Solutions

  1. Pass a *system.CombinedData as dest for common.GetData
  2. Check the agent version — with a 0.19+ agent the generic Data path is used and the dest type must match its schema instead
  3. Audit call sites after refactors to keep action/dest pairs consistent

Example fix

// before
var dest any
err := transport.Request(ctx, common.GetData, nil, &dest)
// after
var dest system.CombinedData
err := transport.Request(ctx, common.GetData, nil, &dest)
Defensive patterns

Strategy: type-guard

Validate before calling

if action == common.GetData {
    if _, ok := dest.(*system.CombinedData); !ok {
        return fmt.Errorf("GetData requires *system.CombinedData, got %T", dest)
    }
}

Type guard

func isCombinedData(dest any) bool {
    _, ok := dest.(*system.CombinedData)
    return ok
}

Try / catch

err := t.Request(ctx, common.GetData, nil, dest)
if err != nil && strings.Contains(err.Error(), "unexpected dest type for GetData") {
    return fmt.Errorf("caller bug: wrong dest type for GetData: %w", err)
}

Prevention

When it happens

Trigger: Calling Request with action GetData but dest not a *system.CombinedData, on a code path where the agent returned an empty Data field (legacy agent), forcing the legacy branch.

Common situations: Refactors changing the dest type without updating all call sites; generic helper functions passing *any or a wrapper struct; mixing new/old hub code with legacy agents.

Related errors


AI-assisted analysis of henrygd/beszel@b38fb7dafa (2026-08-31). Data as JSON: /api/errors/f98e76c2a298d8bb. Report an issue: GitHub.