decolua/9router · warning · Error
`HTTP ${res.status}`
Error message
`HTTP ${res.status}` What it means
ChangelogModal fetches markdown from GITHUB_CONFIG.changelogUrl and throws `HTTP ${res.status}` whenever the response is not ok (non-2xx). The thrown message is caught in the same effect and shown as the modal's error text. It is a thin HTTP-status passthrough, so the message is literally like 'HTTP 404' or 'HTTP 403'.
Source
Thrown at src/shared/components/ChangelogModal.js:23
import PropTypes from "prop-types";
import { marked } from "marked";
import { GITHUB_CONFIG } from "@/shared/constants/config";
marked.setOptions({ gfm: true, breaks: true });
export default function ChangelogModal({ isOpen, onClose }) {
const [html, setHtml] = useState("");
const [loading, setLoading] = useState(false);
const [error, setError] = useState("");
const modalRef = useRef(null);
useEffect(() => {
if (!isOpen || html) return;
setLoading(true);
setError("");
fetch(GITHUB_CONFIG.changelogUrl)
.then((res) => {
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.text();
})
.then((md) => setHtml(marked.parse(md)))
.catch((err) => setError(err.message || "Failed to load"))
.finally(() => setLoading(false));
}, [isOpen, html]);
useEffect(() => {
const handleClickOutside = (e) => {
if (modalRef.current && !modalRef.current.contains(e.target)) {
onClose();
}
};
if (isOpen) {
document.addEventListener("mousedown", handleClickOutside);
return () => document.removeEventListener("mousedown", handleClickOutside);
}
}, [isOpen, onClose]);View on GitHub (pinned to 90b52e06ff)
Solutions
- Check GITHUB_CONFIG.changelogUrl points to an existing file (open it in a browser); fix owner/repo/branch/path if it 404s
- If 403, wait out the GitHub rate limit or use an authenticated/raw URL with caching
- Verify network access to the host (curl the URL); configure proxy if blocked
- Render a fallback: link the user to the changelog page on GitHub when fetch fails
Example fix
// before
if (!res.ok) throw new Error(`HTTP ${res.status}`);
// after
if (!res.ok) throw new Error(`Changelog load failed (HTTP ${res.status}). Check ${GITHUB_CONFIG.changelogUrl}`); Defensive patterns
Strategy: try-catch
Validate before calling
const res = await fetch(GITHUB_CONFIG.changelogUrl, { method: "HEAD" });
if (!res.ok) console.warn("Changelog unavailable:", res.status); Type guard
function isOk(res) { return res && typeof res.ok === "boolean" && res.ok; } Try / catch
try {
const res = await fetch(GITHUB_CONFIG.changelogUrl);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
setHtml(marked.parse(await res.text()));
} catch (err) {
setError(err.message || "Failed to load");
// show fallback link to the changelog on GitHub
} Prevention
- Pin changelogUrl to a stable tag/commit, not a moving branch
- Add retry with backoff for transient GitHub 5xx/403 rate limits
- Cache the last successfully loaded changelog for offline display
- Keep GITHUB_CONFIG owner/repo in sync with repo renames
When it happens
Trigger: fetch(GITHUB_CONFIG.changelogUrl) resolving with res.ok === false — e.g. 404 when CHANGELOG.md does not exist at that path/branch in the repo, 403 from GitHub rate limiting, 5xx from GitHub, or a network-level redirect to an error page.
Common situations: Repo renamed/branch renamed so the raw changelog URL 404s; GitHub API/raw rate limit (403) after many requests; offline or corporate proxy blocking raw.githubusercontent.com; misconfigured GITHUB_CONFIG owner/repo values.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- `HTTP ${res.status}`
- Failed to fetch image: ${res.status}
- Failed to get device code: ${error}
- Failed to get Copilot token: ${error}
- Failed to get user info: ${error}
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/32e2fa9072543a14.
Report an issue: GitHub.