denoland/deno · warning
Deno.autoUpdate: latest.json is not valid JSON
Error message
Deno.autoUpdate: latest.json is not valid JSON
What it means
During a periodic auto-update check, Deno fetched <base>/latest.json and got an HTTP 200 response, but the body failed JSON.parse (cli/rt/desktop.rs:1037-1041). The runtime treats the manifest as unusable, warns, and skips this check round. The app stays on its current version; the next interval tick will retry.
Source
Thrown at cli/rt/desktop.rs:1110
return;
}}
const base = url.replace(/\/$/, "");
const te = new TextEncoder();
const check = async () => {{
try {{
const resp = await fetch(base + "/latest.json", {{
cache: "no-store",
redirect: "error",
}});
if (!resp.ok) return;
const manifestText = await resp.text();
let manifest;
try {{
manifest = JSON.parse(manifestText);
}} catch {{
console.warn("Deno.autoUpdate: latest.json is not valid JSON");
return;
}}
if (manifest.version === _version) return;
if (publicKey) {{
const sig = manifest.signature;
if (typeof sig !== "string" || !sig) {{
console.error(
"Deno.autoUpdate: publicKey configured but manifest has no signature",
);
return;
}}
// Signature is computed over the manifest with the `signature` field
// removed, serialized canonically. To avoid depending on a JCS
// implementation, signers must put the signature on a top-level
// `signature` field and include the rest of the manifest verbatim
// under a `signed` field (string). We then verify over that string.
const signed = manifest.signed;View on GitHub (pinned to f7822238ca)
Solutions
- curl -f <base>/latest.json from a clean network and run the body through a JSON validator to see the exact parse error
- Fix the server so /latest.json serves real JSON with Content-Type: application/json (disable HTML fallback for that path)
- Republish latest.json as strict JSON: no comments, no trailing commas, no BOM
- Check any proxy/CDN in front of the update host for body rewriting or truncation
Example fix
# before: updates.example.com serves the SPA fallback for /myapp/latest.json
$ curl -s https://updates.example.com/myapp/latest.json
<html><body>404</body></html> # 200 + HTML -> 'not valid JSON' warning
# after: strict JSON manifest
{"version":"1.2.0","patches":{"1.1.0":{"name":"1.1.0-to-1.2.0.patch","sha256":"ab..."}}} Defensive patterns
Strategy: validation
Validate before calling
// CI: validate exactly what the app will fetch before you publish
const res = await fetch(`${BASE}/latest.json`);
if (!res.ok) throw new Error(`latest.json unreachable: ${res.status}`);
const manifest = JSON.parse(await res.text()); // throws if the host serves anything but strict JSON
if (typeof manifest?.version !== "string" || typeof manifest?.patches !== "object") {
throw new Error("latest.json: missing version/patches");
} Type guard
function isManifest(v: unknown): v is { version: string; patches: Record<string, { name: string; sha256: string }> } {
if (typeof v !== "object" || v === null) return false;
const m = v as { version?: unknown; patches?: unknown };
return typeof m.version === "string" && typeof m.patches === "object" && m.patches !== null;
} Prevention
- Serve latest.json with Content-Type: application/json and no HTML/SPA fallback on that path
- Lint the manifest in CI with strict JSON.parse before publishing
- Disable CDN rewriting or minification on the update path
- Keep the interval option set so a transient bad body is retried on the next tick
When it happens
Trigger: The update server returns 200 with non-JSON content: an HTML error/SPA fallback page, a truncated body, a BOM-prefixed file, a JSONC file with comments/trailing commas, or proxy/CDN-injected markup. Note resp.ok was already true, so this is purely a body-parsing failure, and redirect: 'error' means a redirect would have failed earlier, not here.
Common situations: Static hosts configured to serve index.html for unknown paths; hand-edited latest.json with a trailing comma; CDN transformations applied to the update path; publishing latest.json as JSONC from the release script.
Understand the failure class
Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.
Related errors
- Deno.autoUpdate: no patch available for
- Deno.autoUpdate: no version in deno.json, skipping
- Deno.autoUpdate: missing 'url' option, skipping
- Deno.autoUpdate: check failed:
- Either `node` or `range` must be provided when reporting an
AI-assisted analysis of denoland/deno@f7822238ca (2026-08-20).
Data as JSON: /api/errors/925b2196b92ee5ea.
Report an issue: GitHub.