{"record":{"id":"0f93d23a6e81ae9d","repo":"sigoden/dufs","slug":"invalid-status-res-status","errorCode":null,"errorMessage":"Invalid status ${res.status}","messagePattern":"Invalid status (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"assets/index.js","lineNumber":974,"sourceCode":"}\n\nfunction formatPercent(percent) {\n  if (percent > 10) {\n    return percent.toFixed(1) + \"%\";\n  } else {\n    return percent.toFixed(2) + \"%\";\n  }\n}\n\nfunction encodedStr(rawStr) {\n  return rawStr.replace(/[\\u00A0-\\u9999<>\\&]/g, function (i) {\n    return '&#' + i.charCodeAt(0) + ';';\n  });\n}\n\nasync function assertResOK(res) {\n  if (!(res.status >= 200 && res.status < 300)) {\n    throw new Error(await res.text() || `Invalid status ${res.status}`);\n  }\n}\n\nfunction getEncoding(contentType) {\n  const charset = contentType?.split(\";\")[1];\n  if (/charset/i.test(charset)) {\n    let encoding = charset.split(\"=\")[1];\n    if (encoding) {\n      return encoding.toLowerCase();\n    }\n  }\n  return 'utf-8';\n}\n\n// Parsing base64 strings with Unicode characters\nfunction decodeBase64(base64String) {\n  const binString = atob(base64String);\n  const len = binString.length;","sourceCodeStart":956,"sourceCodeEnd":992,"githubUrl":"https://github.com/sigoden/dufs/blob/fe7fd564f80dfbac361c8e0589c3845638149d38/assets/index.js#L956-L992","documentation":"assertResOK is a shared helper in dufs's frontend that unwraps fetch responses: if the HTTP status is outside 200-299 it throws the response body text, falling back to 'Invalid status <code>'. It converts any failed server API call (directory listings, uploads, searches, mkdir, etc.) into a thrown Error so the UI code can handle it uniformly.","triggerScenarios":"Any frontend fetch() to the dufs REST API that returns a non-2xx status: 401/403 from missing or wrong Authorization on protected paths, 404 for deleted paths, 409 for existing entries on mkdir/move, 500 from server-side I/O failures.","commonSituations":"Edited files without authentication while the path is protected by --auth; uploading to a read-only share; renaming/moving onto an existing target; server disk errors; stale links after the directory tree changed.","solutions":["Read the thrown body text — it usually carries the server's precise reason","Add correct Authorization (basic auth) headers or log in before the operation","Check that the target path/file exists and permissions allow the operation","For uploads/moves, pick a non-conflicting target name (409 means it exists)","Check dufs server logs for the underlying 5xx cause"],"exampleFix":"// before\nconst res = await fetch(url);\nawait assertResOK(res);\n// after\nconst res = await fetch(url, { headers: authHeaders() });\ntry {\n  await assertResOK(res);\n} catch (msg) {\n  showToast(`Request failed (${res.status}): ${msg}`);\n  if (res.status === 401) promptLogin();\n}","handlingStrategy":"try-catch","validationCode":"const res = await fetch(url, { headers });\nif (!res.ok) console.warn(\"request will fail\", res.status, await res.clone().text());","typeGuard":"function isOkStatus(status) { return status >= 200 && status < 300; }","tryCatchPattern":"try {\n  const res = await fetch(url, { headers });\n  await assertResOK(res);\n} catch (bodyText) {\n  console.error(`API error ${res.status}: ${bodyText}`);\n  if (res.status === 401) promptLogin();\n  else if (res.status === 409) alert(\"Target already exists\");\n}","preventionTips":["Always send auth headers for protected paths","Check existence before mkdir/move/rename to avoid 409/404","Surface the thrown body text to the user — it contains the server reason","Log res.status alongside the message for debugging"],"tags":["javascript","fetch","http-status","api"],"backgroundTag":"http-non-2xx-response","analyzedSha":"fe7fd564f80dfbac361c8e0589c3845638149d38","analyzedAt":"2026-09-09T13:01:22.843Z","contentChangedAt":"2026-09-09T13:01:22.843Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}