gitbutlerapp/gitbutler · warning
Failed to fetch from RSS feed:
Error message
Failed to fetch from RSS feed:
What it means
The web app fetches its YouTube playlist JSON from an API; on a non-ok response or a thrown fetch/JSON error it warns and falls back to getGitButlerPlaylistFallback(), a hardcoded curated list keyed by playlistId. The page always renders a playlist, at the cost of serving stale videos whenever the fetch path fails.
Source
Thrown at apps/web/src/lib/youtube.ts:108
export async function fetchPlaylistVideos(playlistId: string): Promise<YouTubePlaylist> {
try {
const response = await fetch(`${env.PUBLIC_APP_HOST}api/youtube/playlist`, {
// Add timeout to prevent hanging
signal: AbortSignal.timeout(10000),
});
if (response.ok) {
const data = (await response.json()) as { videos: APIYouTubeVideo[] };
const videos = data.videos.map(mapAPIToYouTubeVideo);
return {
id: playlistId,
title: "GitButler Feature Updates",
description: "Latest GitButler tutorials, feature demonstrations, and updates",
videos,
};
}
} catch (error) {
console.warn("Failed to fetch from RSS feed:", error);
}
// Fallback to hardcoded playlist data for the specific GitButler playlist
return getGitButlerPlaylistFallback(playlistId);
}
/**
* Fallback data with actual GitButler video information
* This can be updated manually when new videos are added to the playlist
*/
function getGitButlerPlaylistFallback(playlistId: string): YouTubePlaylist {
const videos: YouTubeVideo[] = [
{
id: "NOYK7LTFvZM",
title: "Using Cursor Hooks for automatic version control",
description:
"Here we demonstrate how to use GitButler with the new Cursor Hooks functionality to automate creating branches for chat sessions and committing work as you go with smart commit messages. Never lose a step again.",
thumbnail: "https://img.youtube.com/vi/NOYK7LTFvZM/maxresdefault.jpg",View on GitHub (pinned to caf1f223d3)
Solutions
- Verify network and the API response status in devtools, then retry when back online
- If videos look stale, update the hardcoded fallback list — it is curated manually by design
- Fix or escalate the API if it consistently returns non-ok
- Cache the last successful response client-side so the fallback stays fresher
Defensive patterns
Strategy: fallback
Validate before calling
async function reachable(url: string): Promise<boolean> {
try {
const res = await fetch(url, { method: "HEAD" });
return res.ok;
} catch {
return false;
}
} Type guard
function isNetworkFailure(e: unknown): boolean {
return e instanceof TypeError; // fetch rejects with TypeError on network-level failure
} Try / catch
try {
return await fetchPlaylist(playlistId);
} catch (error) {
console.warn("Failed to fetch from RSS feed:", error);
return getGitButlerPlaylistFallback(playlistId); // degrade, never throw
} Prevention
- Always pair remote playlist data with a curated fallback, as this code does
- Use AbortSignal.timeout() to fail fast instead of hanging
- Cache the last successful payload in localStorage
When it happens
Trigger: fetch() rejects (offline, DNS failure, timeout), the API returns non-200 (4xx/5xx), or response.json() throws on a malformed body — each lands in the catch at apps/web/src/lib/youtube.ts:108 and activates the hardcoded fallback.
Common situations: Offline browsing or flaky mobile networks; the playlist API rate-limited or down; CDN or edge misconfiguration; an API response shape change breaking mapAPIToYouTubeVideo.
Related errors
- Invalid playlist URL
- push failed
- Download of {url} failed with HTTP status: {response_code}
- Download failed with HTTP status: {response_code}
- system clock is before the Unix epoch: {err}
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/d3812b180308ece7.
Report an issue: GitHub.