{"record":{"id":"d657a1c02b9f6b57","repo":"henrygd/beszel","slug":"unexpected-dest-type-for-checkfingerprint-t","errorCode":null,"errorMessage":"unexpected dest type for CheckFingerprint: %T","messagePattern":"unexpected dest type for CheckFingerprint: %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/hub/transport/transport.go","lineNumber":63,"sourceCode":"}\n\n// unmarshalLegacyResponse handles legacy responses that use typed fields.\nfunc unmarshalLegacyResponse(resp common.AgentResponse, action common.WebSocketAction, dest any) error {\n\tswitch action {\n\tcase common.GetData:\n\t\td, ok := dest.(*system.CombinedData)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"unexpected dest type for GetData: %T\", dest)\n\t\t}\n\t\tif resp.SystemData == nil {\n\t\t\treturn errors.New(\"no system data in response\")\n\t\t}\n\t\t*d = *resp.SystemData\n\t\treturn nil\n\tcase common.CheckFingerprint:\n\t\td, ok := dest.(*common.FingerprintResponse)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"unexpected dest type for CheckFingerprint: %T\", dest)\n\t\t}\n\t\tif resp.Fingerprint == nil {\n\t\t\treturn errors.New(\"no fingerprint in response\")\n\t\t}\n\t\t*d = *resp.Fingerprint\n\t\treturn nil\n\tcase common.GetContainerLogs:\n\t\td, ok := dest.(*string)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"unexpected dest type for GetContainerLogs: %T\", dest)\n\t\t}\n\t\tif resp.String == nil {\n\t\t\treturn errors.New(\"no logs in response\")\n\t\t}\n\t\t*d = *resp.String\n\t\treturn nil\n\tcase common.GetContainerInfo:\n\t\td, ok := dest.(*string)","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/henrygd/beszel/blob/b38fb7dafa60812cc22e6a84ce313e94f1ce0a32/internal/hub/transport/transport.go#L45-L81","documentation":"In the legacy fallback of unmarshalLegacyResponse, action common.CheckFingerprint requires dest to be *common.FingerprintResponse; any other destination type triggers 'unexpected dest type for CheckFingerprint: %T'. It protects the copy from resp.Fingerprint into the caller's target.","triggerScenarios":"Calling Request with action CheckFingerprint and a dest other than *common.FingerprintResponse while the agent response has no generic Data (legacy 0.18.x agent), forcing the typed-field branch.","commonSituations":"Refactors or generic wrappers passing the wrong dest; fingerprint-check helpers rewritten to use a new struct while still hitting legacy agents.","solutions":["Pass a *common.FingerprintResponse as dest for common.CheckFingerprint","Ensure agents are upgraded so responses populate the generic Data field, avoiding the legacy branch","Grep call sites for CheckFingerprint and confirm dest types match"],"exampleFix":"// before\nvar dest map[string]any\nerr := transport.Request(ctx, common.CheckFingerprint, fpReq, &dest)\n// after\nvar dest common.FingerprintResponse\nerr := transport.Request(ctx, common.CheckFingerprint, fpReq, &dest)","handlingStrategy":"type-guard","validationCode":"if action == common.CheckFingerprint {\n    if _, ok := dest.(*common.FingerprintResponse); !ok {\n        return fmt.Errorf(\"CheckFingerprint requires *common.FingerprintResponse, got %T\", dest)\n    }\n}","typeGuard":"func isFingerprintResponse(dest any) bool {\n    _, ok := dest.(*common.FingerprintResponse)\n    return ok\n}","tryCatchPattern":"err := t.Request(ctx, common.CheckFingerprint, req, dest)\nif err != nil && strings.Contains(err.Error(), \"unexpected dest type for CheckFingerprint\") {\n    return fmt.Errorf(\"caller bug: wrong dest type for CheckFingerprint: %w\", err)\n}","preventionTips":["Always pass *common.FingerprintResponse for CheckFingerprint","Use typed wrapper functions instead of raw any-dest calls","Check agent version; modern agents avoid the legacy branch","Keep action/dest pairs documented next to call sites"],"tags":["type-mismatch","legacy-compat","programming-error"],"backgroundTag":"unexpected-response-type","analyzedSha":"b38fb7dafa60812cc22e6a84ce313e94f1ce0a32","analyzedAt":"2026-08-31T15:10:10.149Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}