datawhalechina/hello-agents · error
HTTP error: ${response.status}
Error message
HTTP error: ${response.status} What it means
Guard in startNewGame(): POST to a HARDCODED http://localhost:8000/api/game/start that throws on any non-2xx status. Because the URL is hardcoded, deploying this frontend anywhere non-local guarantees either CORS failures (which reject fetch entirely) or 4xx/5xx that land here.
Source
Thrown at Co-creation-projects/afei-GuessWhoAmI/frontend/app.js:51
// Play again button (HTML id="play-again")
document.getElementById('play-again')
.addEventListener('click', () => this.restartGame());
}
// Start new game
async startNewGame() {
try {
this.setStartBtnLoading(true);
this.showLoadingOverlay();
const response = await fetch('http://localhost:8000/api/game/start', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({})
});
if (!response.ok) throw new Error(`HTTP error: ${response.status}`);
const result = await response.json();
if (!result.success) throw new Error(result.error || '启动失败');
const data = result.data;
this.sessionId = data.session_id;
this.remainingQuestions = data.max_questions || 20;
this.remainingHints = data.max_hints || 3;
// Switch to game screen
document.getElementById('intro-section').classList.add('hidden');
document.getElementById('game-section').classList.remove('hidden');
document.getElementById('result-modal').classList.add('hidden');
// Enable controls
document.getElementById('user-input').disabled = false;
document.getElementById('send-btn').disabled = false;View on GitHub (pinned to 606a07d341)
Solutions
- Replace the hardcoded URL with a config-derived base: same-origin '' in production behind one proxy, or import.meta.env.VITE_API_BASE / window.location.origin fallback in dev
- Confirm the backend actually serves /api/game/start on 8000 (curl -i -X POST http://localhost:8000/api/game/start)
- Enable CORS on the backend for the frontend origin if you keep cross-origin calls
- If 422/500, read response body detail and include it in the thrown error
Example fix
// before
const response = await fetch('http://localhost:8000/api/game/start', {...});
// after
const API_BASE = window.location.origin.startsWith('http://localhost') ? '' : (window.API_BASE_URL || '');
const response = await fetch(`${API_BASE}/api/game/start`, {...}); Defensive patterns
Strategy: validation
Validate before calling
const API_BASE = import.meta.env?.VITE_API_BASE ?? (location.hostname === 'localhost' ? 'http://localhost:8000' : '');
Try / catch
try { await startNewGame(); } catch (e) { alert(`启动失败:${e.message}`); } Prevention
- Never hardcode localhost URLs — derive base from config/env
- Health-check the API on app boot and show setup instructions if unreachable
- Add backend CORS for the dev origin
When it happens
Trigger: Backend not running on port 8000 of the user's machine; accessing the deployed site from another device (localhost refers to the visitor's machine); backend returns 422/500 on start; reverse proxy at a different path.
Common situations: Site deployed to Vercel/GitHub Pages but backend is a local demo server; teammate opens the page on their laptop where nothing listens on 8000; backend moved to /api prefix change or port change.
Related errors
AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14).
Data as JSON: /api/errors/6beec576ff922029.
Report an issue: GitHub.