{"record":{"id":"27e56eb74e7003ca","repo":"henrygd/beszel","slug":"unexpected-dest-type-for-getcontainerlogs-t","errorCode":null,"errorMessage":"unexpected dest type for GetContainerLogs: %T","messagePattern":"unexpected dest type for GetContainerLogs: %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/hub/transport/transport.go","lineNumber":73,"sourceCode":"\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)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"unexpected dest type for GetContainerInfo: %T\", dest)\n\t\t}\n\t\tif resp.String == nil {\n\t\t\treturn errors.New(\"no info in response\")\n\t\t}\n\t\t*d = *resp.String\n\t\treturn nil\n\tcase common.GetSmartData:\n\t\tswitch d := dest.(type) {","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/henrygd/beszel/blob/b38fb7dafa60812cc22e6a84ce313e94f1ce0a32/internal/hub/transport/transport.go#L55-L91","documentation":"For legacy responses, unmarshalLegacyResponse requires dest to be *string when action is common.GetContainerLogs; otherwise it returns 'unexpected dest type for GetContainerLogs: %T'. The container logs are delivered in the typed resp.String field and copied only into a *string target.","triggerScenarios":"Calling Request with GetContainerLogs but dest is e.g. *bytes.Buffer, *[]byte, or a custom log struct, on a path where the response has empty Data (legacy agent) so the legacy branch runs.","commonSituations":"Call sites updated to a richer log type after an upgrade but still talking to old agents; generic request helpers passing non-string destinations.","solutions":["Pass a *string as dest for common.GetContainerLogs","Upgrade the agent so the generic Data path handles richer types","Fix mismatched call sites found via grep for GetContainerLogs"],"exampleFix":"// before\nvar logs []byte\nerr := transport.Request(ctx, common.GetContainerLogs, logReq, &logs)\n// after\nvar logs string\nerr := transport.Request(ctx, common.GetContainerLogs, logReq, &logs)","handlingStrategy":"type-guard","validationCode":"if action == common.GetContainerLogs {\n    if _, ok := dest.(*string); !ok {\n        return fmt.Errorf(\"GetContainerLogs requires *string, got %T\", dest)\n    }\n}","typeGuard":"func isStringPtr(dest any) bool {\n    _, ok := dest.(*string)\n    return ok\n}","tryCatchPattern":"err := t.Request(ctx, common.GetContainerLogs, req, dest)\nif err != nil && strings.Contains(err.Error(), \"unexpected dest type for GetContainerLogs\") {\n    return fmt.Errorf(\"caller bug: wrong dest type for GetContainerLogs: %w\", err)\n}","preventionTips":["Always pass *string for GetContainerLogs","Centralize transport calls in typed helpers per action","Upgrade agents so the generic Data path handles other dest types","Review call sites when changing response types"],"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"}