{"record":{"id":"123f981cc3fe1fe5","repo":"glanceapp/glance","slug":"w-v-123f98","errorCode":null,"errorMessage":"%w: %v","messagePattern":"%w: %v","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/glance/widget-videos.go","lineNumber":163,"sourceCode":"\t\tvar feedUrl string\n\t\tif strings.HasPrefix(channelOrPlaylistIDs[i], videosWidgetPlaylistPrefix) {\n\t\t\tfeedUrl = \"https://www.youtube.com/feeds/videos.xml?playlist_id=\" +\n\t\t\t\tstrings.TrimPrefix(channelOrPlaylistIDs[i], videosWidgetPlaylistPrefix)\n\t\t} else if !includeShorts && strings.HasPrefix(channelOrPlaylistIDs[i], \"UC\") {\n\t\t\tplaylistId := strings.Replace(channelOrPlaylistIDs[i], \"UC\", \"UULF\", 1)\n\t\t\tfeedUrl = \"https://www.youtube.com/feeds/videos.xml?playlist_id=\" + playlistId\n\t\t} else {\n\t\t\tfeedUrl = \"https://www.youtube.com/feeds/videos.xml?channel_id=\" + channelOrPlaylistIDs[i]\n\t\t}\n\n\t\trequest, _ := http.NewRequest(\"GET\", feedUrl, nil)\n\t\trequests = append(requests, request)\n\t}\n\n\tjob := newJob(decodeXmlFromRequestTask[youtubeFeedResponseXml](defaultHTTPClient), requests).withWorkers(30)\n\tresponses, errs, err := workerPoolDo(job)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"%w: %v\", errNoContent, err)\n\t}\n\n\tvideos := make(videoList, 0, len(channelOrPlaylistIDs)*15)\n\tvar failed int\n\n\tfor i := range responses {\n\t\tif errs[i] != nil {\n\t\t\tfailed++\n\t\t\tslog.Error(\"Failed to fetch youtube feed\", \"channel\", channelOrPlaylistIDs[i], \"error\", errs[i])\n\t\t\tcontinue\n\t\t}\n\n\t\tresponse := responses[i]\n\n\t\tfor j := range response.Videos {\n\t\t\tv := &response.Videos[j]\n\t\t\tvar videoUrl string\n","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/glanceapp/glance/blob/91324e8de762702e97b0ac5c8e36271d644d8642/internal/glance/widget-videos.go#L145-L181","documentation":"Returned by the videos widget when the worker pool itself failed before any per-request results existed (workerPoolDo returned a non-nil err). The message wraps errNoContent, so the widget is treated as having no content to render rather than crashing the page.","triggerScenarios":"workerPoolDo fails outright — e.g. all 30 workers unable to start/finish the batch — before individual youtube.com/feeds/videos.xml requests are even attempted; distinct from per-feed errs[] entries which are counted as 'failed'.","commonSituations":"System resource exhaustion (goroutine/thread limits in a tight container) or an internal pool misconfiguration; effectively a rare infrastructure failure, not a config error.","solutions":["Check surrounding logs for the underlying %v cause printed in the message","Restart the Glance process to clear stuck worker state","Reduce concurrent load (fewer channels or longer cache) if the host is resource-constrained"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":"func isNoContent(err error) bool { return errors.Is(err, errNoContent) }","tryCatchPattern":"videos, err := widget.getVideos()\nif errors.Is(err, errNoContent) {\n    // render the widget's empty/no-content state rather than failing the page\n    renderNoContent()\n    return nil\n}","preventionTips":["Keep channel counts and worker concurrency reasonable for the host's resources","Treat errNoContent as an expected state, not an exception — always check it with errors.Is"],"tags":["youtube","worker-pool","no-content","widget"],"backgroundTag":null,"analyzedSha":"91324e8de762702e97b0ac5c8e36271d644d8642","analyzedAt":"2026-08-15T14:12:54.279Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}