henrygd/beszel · error

failed to unmarshal generic response data: %w

Error message

failed to unmarshal generic response data: %w

What it means

UnmarshalResponse (internal/hub/transport/transport.go:39) first tries the generic Data field used by 0.19+ agents. If resp.Data is non-empty but cbor.Unmarshal(resp.Data, dest) fails, it returns 'failed to unmarshal generic response data'. This means the payload was received but its shape/type does not match the caller's destination type.

Source

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

	// The dest parameter should be a pointer to the expected response type.
	Request(ctx context.Context, action common.WebSocketAction, req any, dest any) error
	// IsConnected returns true if the transport connection is active.
	IsConnected() bool
	// Close terminates the transport connection.
	Close()
}

// UnmarshalResponse unmarshals an AgentResponse into the destination type.
// It first checks the generic Data field (0.19+ agents), then falls back
// to legacy typed fields for backward compatibility with 0.18.0 agents.
func UnmarshalResponse(resp common.AgentResponse, action common.WebSocketAction, dest any) error {
	if dest == nil {
		return errors.New("nil destination")
	}
	// 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")
		}

View on GitHub (pinned to b38fb7dafa)

Solutions

  1. Align hub and agent versions (upgrade both to the same release)
  2. Verify dest matches the documented response type for the action
  3. Read the wrapped cbor error to identify the exact field/type mismatch
  4. If the agent is legacy (0.18.x) with empty Data, ensure fallback path applies — check why Data is non-empty but malformed

Example fix

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

Strategy: validation

Validate before calling

var probe system.CombinedData
if err := cbor.Unmarshal(resp.Data, &probe); err != nil {
    return fmt.Errorf("agent payload incompatible with hub schema: %w", err)
}

Type guard

func isVersionCompatible(hubVer, agentVer string) bool {
    hv, av := semver.Parse(hubVer), semver.Parse(agentVer)
    return av.Major == hv.Major && av.Minor >= 19 // generic Data field era
}

Try / catch

err := t.Request(ctx, action, req, dest)
if err != nil && strings.Contains(err.Error(), "failed to unmarshal generic response data") {
    return fmt.Errorf("hub/agent version mismatch on %s: %w", action, err)
}

Prevention

When it happens

Trigger: Agent/hub version skew: a 0.19+ agent returns Data whose shape differs from what the hub's dest expects; the action's payload type changed between releases; dest is a pointer to the wrong struct for the requested action.

Common situations: Upgrading hub without upgrading agent (or vice versa); custom actions returning changed schemas; passing a mismatched dest pointer (e.g. *string for a GetData call).

Related errors


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