{"record":{"id":"209e812028f39f0f","repo":"AlistGo/alist","slug":"send-timeout","errorCode":null,"errorMessage":"send timeout","messagePattern":"send timeout","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/message/http.go","lineNumber":66,"sourceCode":"\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\")\n\t}\n}\n\nvar HttpInstance = &Http{\n\tReceived: make(chan string),\n\tToSend:   make(chan Message),\n}\n","sourceCodeStart":48,"sourceCodeEnd":83,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/internal/message/http.go#L48-L83","documentation":"'send timeout' is returned by (*Http).WaitSend in internal/message/http.go when the message could not be handed to a receiver on the unbuffered ToSend channel within d seconds. The time.After branch of the select fires, meaning no HTTP message poller picked up the send during the wait window.","triggerScenarios":"WaitSend(msg, d) with no consumer attached to HttpInstance.ToSend for the entire d seconds; consumer blocked on a different request or disconnected; d set too small relative to the poll interval of the frontend.","commonSituations":"Browser tab closed or asleep so its message long-poll stops; frontend poll interval longer than the server-side wait; slow clients on bad networks failing to re-establish the poll in time.","solutions":["Increase the wait duration d to exceed the frontend's maximum poll gap","Verify the message-polling endpoint is reachable and the client reconnects after network drops","On timeout, decide explicitly whether to drop or persist the message; do not retry Send into the same absent consumer","Consider a queue/broker for delivery guarantees if polling is unreliable"],"exampleFix":"// before\nerr := message.HttpInstance.WaitSend(msg, 1)\n\n// after\nerr := message.HttpInstance.WaitSend(msg, 30)","handlingStrategy":"retry","validationCode":"// know your poller cadence before choosing d\n// d must exceed the frontend's max long-poll gap","typeGuard":"func isSendTimeout(err error) bool {\n    return err != nil && err.Error() == \"send timeout\"\n}","tryCatchPattern":"if err := message.HttpInstance.WaitSend(msg, d); isSendTimeout(err) {\n    // retry once after reconnect grace, then drop or persist\n}","preventionTips":["Size the timeout above the client poll interval","Ensure clients reconnect the poll after network drops","Decide a drop/persist policy for timed-out messages","Don't retry into a consumer known to be absent"],"tags":["messaging","timeout","channel"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}