{"record":{"id":"a80e4e2699205e9b","repo":"denoland/deno","slug":"request-url-protocol-must-be-http-or-https","errorCode":null,"errorMessage":"Request url protocol must be 'http:' or 'https:': received '${reqUrl.protocol}'","messagePattern":"Request url protocol must be 'http:' or 'https:': received '(.+?)'","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/cache/01_cache.js","lineNumber":149,"sourceCode":"    request = webidl.converters[\"RequestInfo_DOMString\"](\n      request,\n      prefix,\n      \"Argument 1\",\n    );\n    response = webidl.converters[\"Response\"](response, prefix, \"Argument 2\");\n    // Step 1.\n    let innerRequest = null;\n    // Step 2.\n    if (ObjectPrototypeIsPrototypeOf(RequestPrototype, request)) {\n      innerRequest = toInnerRequest(request);\n    } else {\n      // Step 3.\n      innerRequest = toInnerRequest(new Request(request));\n    }\n    // Step 4.\n    const reqUrl = new URL(innerRequest.url());\n    if (reqUrl.protocol !== \"http:\" && reqUrl.protocol !== \"https:\") {\n      throw new TypeError(\n        `Request url protocol must be 'http:' or 'https:': received '${reqUrl.protocol}'`,\n      );\n    }\n    if (innerRequest.method !== \"GET\") {\n      throw new TypeError(\"Request method must be GET\");\n    }\n    // Step 5.\n    const innerResponse = toInnerResponse(response);\n    // Step 6.\n    if (innerResponse.status === 206) {\n      throw new TypeError(\"Response status must not be 206\");\n    }\n    // Step 7.\n    const varyHeader = getHeader(innerResponse.headerList, \"vary\");\n    if (varyHeader) {\n      const fieldValues = StringPrototypeSplit(varyHeader, \",\");\n      for (let i = 0; i < fieldValues.length; ++i) {\n        const field = fieldValues[i];","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/cache/01_cache.js#L131-L167","documentation":"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.","triggerScenarios":"cache.put(new Request('data:text/plain,hi'), response); cache.put('blob:...', response) or cache.put('file:///...', response) — any scheme other than http:/https:.","commonSituations":"Caching responses built from data: URLs or URL.createObjectURL blobs; reusing service-worker-style cache code against synthesized or local resources.","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."],"exampleFix":"// before\nawait cache.put(new Request(`data:${mime},${text}`), res);\n// after (non-HTTP content belongs in storage, not Cache)\nawait kv.set(['assets', key], text);","handlingStrategy":"validation","validationCode":"const u = new URL(typeof request === 'string' ? request : request.url);\nif (u.protocol === 'http:' || u.protocol === 'https:') {\n  await cache.put(request, response);\n} else {\n  await kv.set(['assets', u.href], response); // non-HTTP content: other storage\n}","typeGuard":null,"tryCatchPattern":"try { await cache.put(req, res); } catch (e) { if (e instanceof TypeError) { /* skip caching, app continues */ } else throw e; }","preventionTips":["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."],"tags":["cache","cache-api","url","service-worker"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}