QuantumNous/new-api · info · Error
Unexpected release payload
Error message
Unexpected release payload
What it means
Thrown when the GitHub releases response is HTTP 200 but the JSON lacks tag_name. The dashboard casts the parsed body to ReleaseInfo without runtime validation, so a proxy interstitial, captive portal HTML page parsed as JSON, or API schema change trips this guard.
Source
Thrown at web/src/features/system-settings/maintenance/update-checker-section.tsx:75
setChecking(true)
try {
const response = await fetch(
'https://api.github.com/repos/Calcium-Ion/new-api/releases/latest',
{
headers: {
Accept: 'application/vnd.github+json',
'User-Agent': 'new-api-dashboard',
},
}
)
if (!response.ok) {
throw new Error(t('Failed to contact GitHub releases API'))
}
const data = (await response.json()) as ReleaseInfo
if (!data?.tag_name) {
throw new Error(t('Unexpected release payload'))
}
if (currentVersion && data.tag_name === currentVersion) {
toast.success(
t('You are running the latest version ({{version}}).', {
version: data.tag_name,
})
)
return
}
setRelease(data)
setDialogOpen(true)
} catch (error) {
const message =
error instanceof Error
? error.message
: t('Failed to check for updates')View on GitHub (pinned to e2c7aa7b10)
Solutions
- Log/inspect the actual parsed body when this fires to see what the endpoint really returned.
- If behind an intercepting proxy, fix network egress so the genuine GitHub API responds, or route the check through the backend.
- Handle body.html_url, body.name, and published_at with defaults so only tag_name is truly mandatory (already the case).
- Verify the repo path (Calcium-Ion/new-api) still exists and the releases API is not returning a 404-shaped 200 from a mirror.
Defensive patterns
Strategy: type-guard
Type guard
interface ReleaseInfo { tag_name: string; name?: string; html_url?: string; published_at?: string }
function isReleaseInfo(data: unknown): data is ReleaseInfo {
return typeof data === 'object' && data !== null &&
typeof (data as ReleaseInfo).tag_name === 'string' &&
(data as ReleaseInfo).tag_name.length > 0
} Try / catch
const data: unknown = await response.json()
if (!isReleaseInfo(data)) {
throw new Error(t('Unexpected release payload'))
} Prevention
- Parse as unknown and narrow with a type guard instead of casting response.json() directly.
- Detect non-JSON/proxy interstitials via content-type check before parsing.
- Keep the update checker non-fatal: log the raw payload shape when validation fails to speed diagnosis.
When it happens
Trigger: response.json() succeeds but yields an object without tag_name: a transparent proxy returning an HTML/JSON hybrid, GitHub API schema drift, an empty object from a caching layer, or a mirror endpoint with a different response shape.
Common situations: Corporate/ISP captive portals intercepting api.github.com; CDN cache serving a truncated body; future GitHub API changes renaming tag_name; custom build environments pointing at a GitHub Enterprise endpoint with a different payload.
Related errors
- Failed to contact GitHub releases API
- Request failed
- Parameter override must be valid JSON format
- Legacy format must be a JSON object
- Channel is not selected
AI-assisted analysis of QuantumNous/new-api@e2c7aa7b10 (2026-08-15).
Data as JSON: /api/errors/653703a81961a6aa.
Report an issue: GitHub.