{"record":{"id":"17085738c7ab3b3a","repo":"jeessy2/ddns-go","slug":"throw-new-error-resp","errorCode":null,"errorMessage":"throw new Error(resp)","messagePattern":"throw new Error\\(resp\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web/writing.html","lineNumber":759,"sourceCode":"  document.getElementById(\"index\").addEventListener('change', e => {\n    configIndex = parseInt(e.target.value);\n    showConf(configIndex);\n  });\n\n  // 初始化dnsConf\n  reloadConf(\"{{.DnsConf}}\");\n</script>\n\n<!-- 日志相关函数和日志初始化 -->\n<script>\n  // 获取日志\n  const getLogs = async (loop = false) => {\n    let logsList = [];\n    try {\n      const resp = await request.get(\"./logs\");\n      // 如果不是数组，说明返回的是错误信息\n      if (!Array.isArray(resp)) {\n        throw new Error(resp);\n      }\n      logsList = resp;\n    } catch (err) {\n      showMessage({\n        content: err.toString(),\n        type: \"error\",\n        duration: 5000,\n      });\n      return;\n    } finally {\n      if (loop) {\n        setTimeout(getLogs, 5 * 1000, true);\n      }\n    }\n    const $logs = document.getElementById(\"logs\");\n    // 判断滚动条是否在底部\n    const isBottom = $logs.scrollHeight - $logs.scrollTop - $logs.clientHeight < 10;\n    $logs.value = logsList.join(\"\");","sourceCodeStart":741,"sourceCodeEnd":777,"githubUrl":"https://github.com/jeessy2/ddns-go/blob/5874c2e6667c69357ab95079421131104bd3fcae/web/writing.html#L741-L777","documentation":"The getLogs function fetches log entries from the ./logs endpoint via request.get. If the response is not an array, the code treats it as an error payload and throws `new Error(resp)`, so the raw (often string/JSON error object) response becomes the Error message. It surfaces in the UI via showMessage with type 'error'.","triggerScenarios":"Calling getLogs() when the ./logs endpoint returns a non-array body — e.g. an auth/permission error page, a JSON object like {code,msg}, HTML from a proxy, or an empty/plain-text error string instead of the expected log array.","commonSituations":"Session expired or not logged in so the server returns an error object; reverse proxy or CDN intercepts the request and returns HTML; backend bug changed the response shape; wrong URL rewritten by a router returning an error page.","solutions":["Check why ./logs returned a non-array: log the raw resp before throwing to see the actual payload","Verify you are authenticated (cookie/token) when calling ./logs; re-login if the session expired","Fix the server/route so the endpoint always returns a JSON array of logs, or the client so it parses resp correctly","Change the throw to include context: throw new Error('logs response is not an array: ' + JSON.stringify(resp))"],"exampleFix":"// before\nif (!Array.isArray(resp)) {\n  throw new Error(resp);\n}\n// after\nif (!Array.isArray(resp)) {\n  throw new Error('获取日志失败: ' + (typeof resp === 'string' ? resp : JSON.stringify(resp)));\n}","handlingStrategy":"type-guard","validationCode":"const resp = await request.get('./logs');\nif (!Array.isArray(resp)) {\n  // handle error payload before proceeding\n  console.error('logs endpoint returned non-array:', resp);\n}","typeGuard":"function isLogArray(v) {\n  return Array.isArray(v) && v.every((e) => typeof e === 'object' && e !== null);\n}","tryCatchPattern":"try {\n  const resp = await request.get('./logs');\n  if (!Array.isArray(resp)) {\n    throw new Error('日志接口返回异常: ' + JSON.stringify(resp));\n  }\n  logsList = resp;\n} catch (err) {\n  showMessage({ content: err.toString(), type: 'error' });\n}","preventionTips":["Always validate the response shape (Array.isArray) before consuming API data","Check authentication state before calling protected endpoints","Log the raw response when validation fails to diagnose proxies/auth issues quickly","Keep client parsing in sync with server response contract via shared types"],"tags":["http-response","javascript","type-mismatch"],"backgroundTag":"unexpected-response-shape","analyzedSha":"5874c2e6667c69357ab95079421131104bd3fcae","analyzedAt":"2026-09-03T15:41:16.799Z","contentChangedAt":"2026-09-03T15:41:16.799Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}