{"record":{"id":"cfca2ff8390554ff","repo":"theonedev/onedev","slug":"failed-to-load-notebook-response-status","errorCode":null,"errorMessage":"Failed to load notebook: {response.status}","messagePattern":"Failed to load notebook: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/web/asset/notebook/notebook-view.js","lineNumber":16,"sourceCode":"onedev.server.notebookView = {\n\trender: async function(containerId, notebookUrl) {\n\t\tconst container = document.getElementById(containerId);\n\t\tif (!container)\n\t\t\treturn;\n\n\t\ttry {\n\t\t\tif (typeof nb !== 'undefined' && typeof marked !== 'undefined') {\n\t\t\t\tnb.markdown = function(text) {\n\t\t\t\t\treturn marked.parse(text);\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst response = await fetch(notebookUrl);\n\t\t\tif (!response.ok)\n\t\t\t\tthrow new Error('Failed to load notebook: ' + response.status);\n\t\t\tconst json = await response.json();\n\n\t\t\tconst notebook = nb.parse(json);\n\t\t\tconst rendered = notebook.render();\n\n\t\t\tcontainer.innerHTML = '';\n\t\t\tcontainer.appendChild(rendered);\n\n\t\t\tonedev.server.notebookView.rewriteRelativeUrls(container, notebookUrl);\n\n\t\t\t$(window).resize();\n\t\t} catch (error) {\n\t\t\tconsole.error(error);\n\t\t\tcontainer.textContent = 'Failed to render notebook: ' + error.message;\n\t\t}\n\t},\n\n\trewriteRelativeUrls: function(container, notebookUrl) {","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/web/asset/notebook/notebook-view.js#L1-L34","documentation":"In notebook-view.js, the Jupyter notebook viewer fetches the notebook JSON from notebookUrl; if the HTTP response is not ok (non-2xx status), it throws \"Failed to load notebook: <status>\" before parsing. This is a fetch-level guard so the nb.parse step never sees an error page or auth HTML instead of notebook JSON.","triggerScenarios":"fetch(notebookUrl) returns a non-ok response: 404 (notebook file missing/deleted), 403/401 (not authorized to read the file or project), or 500 from the server.","commonSituations":"Viewing an .ipynb file whose branch/commit no longer exists; accessing a private project's notebook without login; a reverse proxy returning 404/502 for the asset URL; wrong notebookUrl path passed to the viewer.","solutions":["Check the reported HTTP status: 404 means verify the notebook file path, branch and commit exist; 401/403 means log in or request read access to the project.","Confirm notebookUrl points at the raw notebook content endpoint and is reachable from the browser.","Check server logs if the status is 5xx; fix the server-side error and retry."],"exampleFix":"// before\nconst response = await fetch(notebookUrl);\nif (!response.ok)\n  throw new Error('Failed to load notebook: ' + response.status);\n\n// after (defensive caller)\nconst response = await fetch(notebookUrl);\nif (!response.ok) {\n  container.textContent = response.status === 404\n    ? 'Notebook not found.' : 'Failed to load notebook: ' + response.status;\n} else {\n  const json = await response.json();\n  // render\n}","handlingStrategy":"try-catch","validationCode":"// pre-check reachable before fetch is not possible; validate URL and auth state client-side\nif (!notebookUrl || !notebookUrl.startsWith(window.location.origin))\n    console.warn('Suspicious notebook URL:', notebookUrl);","typeGuard":"function isOkResponse(res) {\n  return res instanceof Response && res.ok;\n}","tryCatchPattern":"try {\n  const res = await fetch(notebookUrl);\n  if (!res.ok) throw new Error('Failed to load notebook: ' + res.status);\n  const json = await res.json();\n} catch (e) {\n  container.textContent = e.status === 404 ? 'Notebook not found' : 'Failed to load notebook';\n}","preventionTips":["Verify the notebook path/branch exists before opening deep links.","Ensure the user is logged in and has read access to the project.","Handle non-ok fetch responses in UI code with a friendly message and the status code."],"tags":["javascript","http","notebook","fetch"],"backgroundTag":"http-error-response","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}