{"record":{"id":"a4255fa7276036a3","repo":"dapr/dapr","slug":"unknown-status-returned-from-app-while-processing-a4255f","errorCode":null,"errorMessage":"unknown status returned from app while processing pub/sub event %v, status: %v, err: %w","messagePattern":"unknown status returned from app while processing pub/sub event (.+?), status: (.+?), err: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/runtime/subscription/postman/streaming/streaming.go","lineNumber":80,"sourceCode":"\tswitch resp.GetStatus().GetStatus() {\n\tcase rtv1pb.TopicEventResponse_SUCCESS: //nolint:nosnakecase\n\t\t// on uninitialized status, this is the case it defaults to as an uninitialized status defaults to 0 which is\n\t\t// success from protobuf definition\n\t\tdiag.DefaultComponentMonitoring.PubsubIngressEvent(ctx, msg.PubSub, strings.ToLower(string(contribpubsub.Success)), \"\", msg.Topic, elapsed)\n\t\treturn nil\n\tcase rtv1pb.TopicEventResponse_RETRY: //nolint:nosnakecase\n\t\tdiag.DefaultComponentMonitoring.PubsubIngressEvent(ctx, msg.PubSub, strings.ToLower(string(contribpubsub.Retry)), \"\", msg.Topic, elapsed)\n\t\t// TODO: add retry error info\n\t\treturn fmt.Errorf(\"RETRY status returned from app while processing pub/sub event %v: %w\", msg.CloudEvent[contribpubsub.IDField], rterrors.NewRetriable(nil))\n\tcase rtv1pb.TopicEventResponse_DROP: //nolint:nosnakecase\n\t\tlog.Warnf(\"DROP status returned from app while processing pub/sub event %v\", msg.CloudEvent[contribpubsub.IDField])\n\t\tdiag.DefaultComponentMonitoring.PubsubIngressEvent(ctx, msg.PubSub, strings.ToLower(string(contribpubsub.Drop)), \"\", msg.Topic, elapsed)\n\n\t\treturn pubsub.ErrMessageDropped\n\tdefault:\n\t\t// Consider unknown status field as error and retry\n\t\tdiag.DefaultComponentMonitoring.PubsubIngressEvent(ctx, msg.PubSub, strings.ToLower(string(contribpubsub.Retry)), \"\", msg.Topic, elapsed)\n\t\treturn fmt.Errorf(\"unknown status returned from app while processing pub/sub event %v, status: %v, err: %w\", msg.CloudEvent[contribpubsub.IDField], resp.GetStatus(), rterrors.NewRetriable(nil))\n\t}\n}\n\nfunc (s *streaming) DeliverBulk(context.Context, *postman.DeliverBulkRequest) error {\n\treturn errors.New(\"not implemented\")\n}\n","sourceCodeStart":62,"sourceCodeEnd":87,"githubUrl":"https://github.com/dapr/dapr/blob/74ad41702745709bb15fe2114ff693b8c59bc3cc/pkg/runtime/subscription/postman/streaming/streaming.go#L62-L87","documentation":"The streaming subscriber's processed response carried a TopicEventResponse status other than SUCCESS, RETRY, or DROP, so daprd treats it as retriable. As with the other unknown-status errors, unset defaults to SUCCESS (0); this fires only on an enum value the running daprd build does not recognize — typically SDK/proto version skew on the alpha streaming API.","triggerScenarios":"Streaming subscriber built against a different dapr proto revision sends a status outside {0,1,2}; custom stream handler assigns a raw enum int; mixed daprd/SDK versions during rollout of the alpha API.","commonSituations":"Early-adopter mismatch between SDK and sidecar on SubscribeTopicEventsAlpha1; hand-implemented streaming clients; proto regenerated from a newer dapr/dapr checkout.","solutions":["Align SDK and daprd versions (streaming subscribe is alpha and changes between releases); redeploy together","In custom stream handlers, respond with SUCCESS/RETRY/DROP only, or omit the status for success","Add deadLetterTopic plus bounded retries so unrecognized statuses terminate in DLQ"],"exampleFix":"// before\nawait stream.Send(&rtv1.SubscribeTopicEventsRequestProcessedAlpha1{\n\tId: id, Status: &rtv1.TopicEventResponse{Status: rtv1.TopicEventResponse(7)},\n})\n\n// after\nawait stream.Send(&rtv1.SubscribeTopicEventsRequestProcessedAlpha1{\n\tId: id, Status: &rtv1.TopicEventResponse{Status: rtv1.TopicEventResponse_SUCCESS},\n})","handlingStrategy":"type-guard","validationCode":"// Normalize the status before writing the processed message to the stream.\nif !isValidTopicEventStatus(s) {\n\ts = rtv1.TopicEventResponse_SUCCESS\n}","typeGuard":"func isValidTopicEventStatus(s rtv1.TopicEventResponse_Status) bool {\n\tswitch s {\n\tcase rtv1.TopicEventResponse_SUCCESS, rtv1.TopicEventResponse_RETRY, rtv1.TopicEventResponse_DROP:\n\t\treturn true\n\t}\n\treturn false\n}","tryCatchPattern":null,"preventionTips":["On alpha APIs, keep SDK and sidecar versions strictly aligned","Omit the status field for success rather than setting it explicitly","Unit-test stream responses against the known enum set","Monitor for 'unknown status' logs during rollouts and halt on skew"],"tags":["grpc","streaming","pubsub","version-skew","alpha"],"backgroundTag":null,"analyzedSha":"74ad41702745709bb15fe2114ff693b8c59bc3cc","analyzedAt":"2026-08-16T04:22:26.543Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}