jamiepine/voicebox · info · Error

Failed to fetch releases

Error message

Failed to fetch releases

What it means

Thrown in the home page useEffect when /api/releases returns non-2xx; caught and console.erroled, leaving version/totalDownloads null. Identical mechanism to the /capture page release fetch — same /api/releases route proxying GitHub.

Source

Thrown at landing/src/app/page.tsx:28

import {Footer} from "@/components/Footer";
import {Navbar} from "@/components/Navbar";
import {Personalities} from "@/components/Personalities";
import {AppleIcon, LinuxIcon, WindowsIcon} from "@/components/PlatformIcons";
import {SupportedModels} from "@/components/SupportedModels";
import {Testimonials} from "@/components/Testimonials";
import {TokenTeaser} from "@/components/TokenTeaser";
import {TutorialsSection} from "@/components/TutorialsSection";
import {VoiceCreator} from "@/components/VoiceCreator";
import {GITHUB_REPO} from "@/lib/constants";

export default function Home() {
	const [version, setVersion] = useState<string | null>(null);
	const [totalDownloads, setTotalDownloads] = useState<number | null>(null);

	useEffect(() => {
		fetch("/api/releases")
			.then((res) => {
				if (!res.ok) throw new Error("Failed to fetch releases");
				return res.json();
			})
			.then((data) => {
				if (data.version) setVersion(data.version);
				if (data.totalDownloads != null) setTotalDownloads(data.totalDownloads);
			})
			.catch((error) => {
				console.error("Failed to fetch release info:", error);
			});
	}, []);

	return (
		<>
			<Navbar />

			{/* ── Hero Section ─────────────────────────────────────────────── */}
			<section className="relative pt-32 pb-16">
				{/* Background glow */}

View on GitHub (pinned to 51f49dea19)

Solutions

  1. Share one cached release fetch across pages (the in-memory cache in releases.ts already helps; ensure pages hit the same cache).
  2. Add a server-side GitHub token to lift the rate limit.
  3. Render the version badge conditionally so null doesn't break layout.
  4. Confirm GITHUB_REPO is the intended public repo.

Example fix

// before
if (!res.ok) throw new Error('Failed to fetch releases');
// after
if (!res.ok) { console.warn('releases status', res.status); return; }
Defensive patterns

Strategy: fallback

Type guard

function isReleasePayload(v: unknown): v is { version?: string; totalDownloads?: number } {
  return typeof v === 'object' && v !== null;
}

Try / catch

try {
  const res = await fetch('/api/releases');
  if (!res.ok) throw new Error('Failed to fetch releases');
  const data = await res.json();
  if (data.version) setVersion(data.version);
} catch (error) {
  console.error('Failed to fetch release info:', error);
}

Prevention

When it happens

Trigger: GET /api/releases returns 500 because getLatestRelease() failed upstream (GitHub 403/429, network, misconfigured GITHUB_REPO).

Common situations: Shared deploy IP exhausts GitHub's unauthenticated rate limit across multiple landing routes all hitting /api/releases. Preview/branch deploys with blocked egress.

Related errors


AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12). Data as JSON: /api/errors/8b1e0598cc688919. Report an issue: GitHub.