denoland/deno · error · TypeError
Request url protocol must be 'http:' or 'https:': received '
Error message
Request url protocol must be 'http:' or 'https:': received '${reqUrl.protocol}' What it means
Cache.put() implements the ServiceWorker Cache API algorithm; step 4 requires the request URL scheme to be http: or https:. The Cache API stores only network resources, so data:, blob:, file: and other schemes are rejected.
Source
Thrown at ext/cache/01_cache.js:149
request = webidl.converters["RequestInfo_DOMString"](
request,
prefix,
"Argument 1",
);
response = webidl.converters["Response"](response, prefix, "Argument 2");
// Step 1.
let innerRequest = null;
// Step 2.
if (ObjectPrototypeIsPrototypeOf(RequestPrototype, request)) {
innerRequest = toInnerRequest(request);
} else {
// Step 3.
innerRequest = toInnerRequest(new Request(request));
}
// Step 4.
const reqUrl = new URL(innerRequest.url());
if (reqUrl.protocol !== "http:" && reqUrl.protocol !== "https:") {
throw new TypeError(
`Request url protocol must be 'http:' or 'https:': received '${reqUrl.protocol}'`,
);
}
if (innerRequest.method !== "GET") {
throw new TypeError("Request method must be GET");
}
// Step 5.
const innerResponse = toInnerResponse(response);
// Step 6.
if (innerResponse.status === 206) {
throw new TypeError("Response status must not be 206");
}
// Step 7.
const varyHeader = getHeader(innerResponse.headerList, "vary");
if (varyHeader) {
const fieldValues = StringPrototypeSplit(varyHeader, ",");
for (let i = 0; i < fieldValues.length; ++i) {
const field = fieldValues[i];View on GitHub (pinned to 89f33cbef2)
Solutions
- Cache only http(s) URLs.
- Store non-HTTP content in Deno KV, SQLite, or the filesystem instead of the Cache API.
- Rebuild the Request from an http(s) URL before put() when a non-network Request object was constructed.
Example fix
// before
await cache.put(new Request(`data:${mime},${text}`), res);
// after (non-HTTP content belongs in storage, not Cache)
await kv.set(['assets', key], text); Defensive patterns
Strategy: validation
Validate before calling
const u = new URL(typeof request === 'string' ? request : request.url);
if (u.protocol === 'http:' || u.protocol === 'https:') {
await cache.put(request, response);
} else {
await kv.set(['assets', u.href], response); // non-HTTP content: other storage
} Try / catch
try { await cache.put(req, res); } catch (e) { if (e instanceof TypeError) { /* skip caching, app continues */ } else throw e; } Prevention
- Reserve the Cache API for http(s) network resources only.
- Route data:, blob:, and file: content to KV/SQLite/filesystem by design, not by exception.
When it happens
Trigger: cache.put(new Request('data:text/plain,hi'), response); cache.put('blob:...', response) or cache.put('file:///...', response) — any scheme other than http:/https:.
Common situations: Caching responses built from data: URLs or URL.createObjectURL blobs; reusing service-worker-style cache code against synthesized or local resources.
Related errors
- Request method must be GET
- Vary header must not contain '*'
- BenchContext::end() has already been invoked
- Object is not a valid image or a path to an image. `Deno.jup
- Response status must not be 206
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/a80e4e2699205e9b.
Report an issue: GitHub.