{"record":{"id":"cc0dd50cc6517557","repo":"AlistGo/alist","slug":"receive-failed","errorCode":null,"errorMessage":"receive failed","messagePattern":"receive failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"internal/message/http.go","lineNumber":57,"sourceCode":"\t\tcommon.ErrorStrResp(c, \"nowhere needed\", 500)\n\t}\n}\n\nfunc (p *Http) Send(message Message) error {\n\tselect {\n\tcase p.ToSend <- message:\n\t\treturn nil\n\tdefault:\n\t\treturn errors.New(\"send failed\")\n\t}\n}\n\nfunc (p *Http) Receive() (string, error) {\n\tselect {\n\tcase message := <-p.Received:\n\t\treturn message, nil\n\tdefault:\n\t\treturn \"\", errors.New(\"receive failed\")\n\t}\n}\n\nfunc (p *Http) WaitSend(message Message, d int) error {\n\tselect {\n\tcase p.ToSend <- message:\n\t\treturn nil\n\tcase <-time.After(time.Duration(d) * time.Second):\n\t\treturn errors.New(\"send timeout\")\n\t}\n}\n\nfunc (p *Http) WaitReceive(d int) (string, error) {\n\tselect {\n\tcase message := <-p.Received:\n\t\treturn message, nil\n\tcase <-time.After(time.Duration(d) * time.Second):\n\t\treturn \"\", errors.New(\"receive timeout\")","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/internal/message/http.go#L39-L75","documentation":"'receive failed' is returned by (*Http).Receive in internal/message/http.go when a non-blocking receive on the Received channel finds no message. The select falls through to default, signaling 'nothing to read right now' rather than an actual fault.","triggerScenarios":"Calling HttpInstance.Receive() when no client has pushed a message into the Received channel (the endpoint that feeds it has not been called), or when a previously sent message was already consumed by another receiver.","commonSituations":"Polling loops that call Receive as a status check instead of using WaitReceive with a timeout; two consumers racing where one drains the only message; frontend disconnected so no inbound messages arrive.","solutions":["Prefer WaitReceive(d) to block for up to d seconds instead of busy-checking Receive()","Ensure only one goroutine consumes HttpInstance.Received to avoid stealing messages","If using Receive() as a probe, treat the error as 'empty', not as a failure worth logging","Verify the sending side (HTTP handler writing to Received) is actually being reached"],"exampleFix":"// before\nmsg, err := message.HttpInstance.Receive()\n\n// after\nmsg, err := message.HttpInstance.WaitReceive(10)","handlingStrategy":"fallback","validationCode":"// probe with non-blocking Receive only when emptiness is expected\n// otherwise go straight to WaitReceive","typeGuard":"func isReceiveFailed(err error) bool {\n    return err != nil && err.Error() == \"receive failed\"\n}","tryCatchPattern":"msg, err := message.HttpInstance.Receive()\nif isReceiveFailed(err) { msg = \"\" /* empty poll */ }","preventionTips":["Use WaitReceive(d) for real waits","Single consumer per channel to avoid message stealing","Treat 'receive failed' as empty, not error","Test with injected messages instead of tight polling"],"tags":["channel","messaging","concurrency"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}