{"record":{"id":"9d7e28fb2389b148","repo":"digininja/DVWA","slug":"network-response-was-not-ok","errorCode":null,"errorMessage":"Network response was not ok","messagePattern":"Network response was not ok","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"vulnerabilities/api/source/low.php","lineNumber":54,"sourceCode":"\t\t}\n\n\t\tconst message_line = document.getElementById ('message');\n\t\tif (user_json.id == 2 && user_json.level == 0) {\n\t\t\tmessage_line.style.display = 'block';\n\t\t} else {\n\t\t\tmessage_line.style.display = 'none';\n\t\t}\n\t}\n\n\tfunction get_users() {\n\t\tconst url = '\" . $stripped_url . \"/vulnerabilities/api/v2/user/';\n\t\t \n\t\tfetch(url, { \n\t\t\t\tmethod: 'GET',\n\t\t\t}) \n\t\t\t.then(response => { \n\t\t\t\tif (!response.ok) { \n\t\t\t\t\tthrow new Error('Network response was not ok'); \n\t\t\t} \n\t\t\treturn response.json(); \n\t\t\t}) \n\t\t\t.then(data => { \n\t\t\t\tloadTableData(data);\n\t\t\t}) \n\t\t\t.catch(error => { \n\t\t\t\tconsole.error('There was a problem with your fetch operation:', error); \n\t\t}); \n\t}\n\n\tHTMLTableRowElement.prototype.insert_th_Cell = function(index) {\n\t\tlet cell = this.insertCell(index)\n\t\t, c_th = document.createElement('th');\n\t\tcell.replaceWith(c_th);\n\t\treturn c_th;\n\t}\n","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/digininja/DVWA/blob/5d5c76cced604e54462b13723f5c69af58e78748/vulnerabilities/api/source/low.php#L36-L72","documentation":"Thrown by the page's own fetch handler in get_users() when GET /vulnerabilities/api/v2/user/ replies with a non-2xx HTTP status; response.ok is only true for 200-299, and the handler converts every other status into this generic Error before response.json() runs. In DVWA that URL is rewritten by vulnerabilities/api/.htaccess to public/index.php, which returns 404 for unrecognized paths, 404 for unknown user ids, and 500 when the composer vendor directory is missing (bootstrap.php fatals on require 'vendor/autoload.php').","triggerScenarios":"Calling get_users() (it runs automatically on page load) when mod_rewrite is disabled or AllowOverride prevents the .htaccess rewrite, so /v2/user/ hits a real 404; when 'composer install' was never run inside vulnerabilities/api/ so the front controller dies with HTTP 500; when the query string of $_SERVER['REQUEST_URI'] leaks into $stripped_url and the concatenated fetch URL is malformed; or when the router sees a path that does not match /v[0-9]/(user|order|login|health).","commonSituations":"Fresh DVWA clone where composer dependencies were skipped; Apache without mod_rewrite or with AllowOverride None; accessing the page through a URL carrying extra query parameters; renaming the api directory or moving DVWA under a subpath while assuming hard-coded routing.","solutions":["Open DevTools > Network and re-run the request to see the real status code (404 vs 500 points to routing vs fatal).","Run composer install inside vulnerabilities/api/ to fix the 500 caused by the missing vendor/autoload.php require.","Enable mod_rewrite (a2enmod rewrite) and set AllowOverride All for the DVWA vhost so .htaccess routes /v2/* to public/index.php.","View the generated page source and verify the fetch URL is a clean path ending in /vulnerabilities/api/v2/user/ with no query-string fragment from $stripped_url.","Sanity-check the router with GET /vulnerabilities/api/v2/user/1 (seeded user) directly in the browser."],"exampleFix":"// before\n.then(response => {\n    if (!response.ok) {\n        throw new Error('Network response was not ok');\n    }\n    return response.json();\n})\n// after\n.then(response => {\n    if (!response.ok) {\n        throw new Error(`Request failed: ${response.status} ${response.statusText}`);\n    }\n    return response.json();\n})","handlingStrategy":"try-catch","validationCode":"function validApiUrl(url) {\n    return /^https?:\\/\\/[^\\/]+\\/vulnerabilities\\/api\\/v\\d+\\/user\\/?$/.test(url);\n}\n// before calling get_users()\nif (!validApiUrl(url)) {\n    console.error('Refusing to fetch malformed API URL:', url);\n    return;\n}","typeGuard":"function isUserList(payload) {\n    return Array.isArray(payload) && payload.every(u =>\n        typeof u === 'object' && u !== null && 'name' in u && 'level' in u);\n}","tryCatchPattern":"async function getUsersSafe(url) {\n    try {\n        const response = await fetch(url, { method: 'GET' });\n        if (!response.ok) {\n            throw new Error(`Request failed: ${response.status} ${response.statusText}`);\n        }\n        const data = await response.json();\n        if (!isUserList(data)) throw new Error('Unexpected payload shape');\n        loadTableData(data);\n    } catch (error) {\n        console.error('There was a problem with your fetch operation:', error);\n    }\n}","preventionTips":["Include response.status and statusText in thrown errors so failures are diagnosable.","Never interpolate REQUEST_URI (with its query string) into a fetch URL - build URLs from a known base path.","Verify deployment prerequisites (composer install, mod_rewrite) before shipping pages that call the API.","Smoke-test the router with a known endpoint after infrastructure changes."],"tags":["javascript","fetch","http-status","rest-api","dvwa"],"backgroundTag":"http-error-status","analyzedSha":"5d5c76cced604e54462b13723f5c69af58e78748","analyzedAt":"2026-08-21T01:20:26.904Z","schemaVersion":2},"datasetVersion":"2026-08-21T03:17:12.404Z"}