theonedev/onedev · error · Error

Failed to load notebook: {response.status}

Error message

Failed to load notebook: {response.status}

What it means

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.

Source

Thrown at server-core/src/main/java/io/onedev/server/web/asset/notebook/notebook-view.js:16

onedev.server.notebookView = {
	render: async function(containerId, notebookUrl) {
		const container = document.getElementById(containerId);
		if (!container)
			return;

		try {
			if (typeof nb !== 'undefined' && typeof marked !== 'undefined') {
				nb.markdown = function(text) {
					return marked.parse(text);
				};
			}

			const response = await fetch(notebookUrl);
			if (!response.ok)
				throw new Error('Failed to load notebook: ' + response.status);
			const json = await response.json();

			const notebook = nb.parse(json);
			const rendered = notebook.render();

			container.innerHTML = '';
			container.appendChild(rendered);

			onedev.server.notebookView.rewriteRelativeUrls(container, notebookUrl);

			$(window).resize();
		} catch (error) {
			console.error(error);
			container.textContent = 'Failed to render notebook: ' + error.message;
		}
	},

	rewriteRelativeUrls: function(container, notebookUrl) {

View on GitHub (pinned to d44925c47c)

Solutions

  1. 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.
  2. Confirm notebookUrl points at the raw notebook content endpoint and is reachable from the browser.
  3. Check server logs if the status is 5xx; fix the server-side error and retry.

Example fix

// before
const response = await fetch(notebookUrl);
if (!response.ok)
  throw new Error('Failed to load notebook: ' + response.status);

// after (defensive caller)
const response = await fetch(notebookUrl);
if (!response.ok) {
  container.textContent = response.status === 404
    ? 'Notebook not found.' : 'Failed to load notebook: ' + response.status;
} else {
  const json = await response.json();
  // render
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check reachable before fetch is not possible; validate URL and auth state client-side
if (!notebookUrl || !notebookUrl.startsWith(window.location.origin))
    console.warn('Suspicious notebook URL:', notebookUrl);

Type guard

function isOkResponse(res) {
  return res instanceof Response && res.ok;
}

Try / catch

try {
  const res = await fetch(notebookUrl);
  if (!res.ok) throw new Error('Failed to load notebook: ' + res.status);
  const json = await res.json();
} catch (e) {
  container.textContent = e.status === 404 ? 'Notebook not found' : 'Failed to load notebook';
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/cfca2ff8390554ff. Report an issue: GitHub.