denoland/deno · error · Error
Deno.jupyter is only available in `deno jupyter` subcommand
Error message
Deno.jupyter is only available in `deno jupyter` subcommand
What it means
Deno.jupyter is published on the final Deno namespace in runtime/js/99_main.js as a lazy accessor: it caches the namespace once the `deno jupyter` bootstrap sets it, but until then the getter throws Error('Deno.jupyter is only available in `deno jupyter` subcommand'). Accessing the property under any other subcommand (deno run, test, repl) throws. Note the accessor property always exists, so presence checks like `'jupyter' in Deno` cannot detect availability — only an actual access inside try/catch can.
Source
Thrown at runtime/js/99_main.js:1131
runtimeStart(
denoVersion,
v8Version,
tsVersion,
target,
);
// TODO(bartlomieju): this is not ideal, but because we use `ObjectAssign`
// above any properties that are defined elsewhere using `Object.defineProperty`
// are lost.
let jupyterNs = undefined;
ObjectDefineProperty(finalDenoNs, "jupyter", {
__proto__: null,
get() {
if (jupyterNs) {
return jupyterNs;
}
throw new Error(
"Deno.jupyter is only available in `deno jupyter` subcommand",
);
},
set(val) {
jupyterNs = val;
},
});
for (let i = 0; i <= unstableFeatures.length; i++) {
const id = unstableFeatures[i];
const unstable = denoNsUnstableById[id];
if (unstable) {
ObjectDefineProperties(
finalDenoNs,
getSafeOwnPropertyDescriptors(unstable),
);
}
}View on GitHub (pinned to a961cdec3b)
Solutions
- Access Deno.jupyter only behind a try/catch probe (see defense) or inside code known to run under `deno jupyter`
- Route display output through console.log generally, and use Deno.jupyter only when the probe succeeds
- Upgrade Deno if you need Deno.jupyter unconditionally — newer versions expose it in every subcommand
Example fix
// before
Deno.jupyter.broadcast('display_data', { data: { 'text/html': html } });
// after
function getJupyter() {
try {
return Deno.jupyter;
} catch {
return undefined;
}
}
const jupyter = getJupyter();
if (jupyter) jupyter.broadcast('display_data', { data: { 'text/html': html } }); Defensive patterns
Strategy: try-catch
Validate before calling
function getJupyter() {
try {
return Deno.jupyter; // touching the property throws outside deno jupyter
} catch {
return undefined;
}
}
const jupyter = getJupyter();
if (jupyter) {
jupyter.broadcast('display_data', payload);
} Try / catch
// wrap every access — even detection — because the getter throws
try {
const { markdown } = Deno.jupyter;
await markdown(md);
} catch {
console.log(md); // plain fallback outside notebooks
} Prevention
- The accessor property always exists, so `'jupyter' in Deno` cannot detect availability — probe by accessing inside try/catch
- Isolate notebook-specific output helpers behind one guarded accessor
- Upgrade Deno if you need Deno.jupyter outside `deno jupyter`; newer versions expose it in every subcommand
When it happens
Trigger: `Deno.jupyter.broadcast('display_data', ...)` in a script run with `deno run`; notebook helper modules reused in plain scripts; probing capabilities by touching Deno.jupyter at import time.
Common situations: Sharing rich-output helpers between notebooks and CLI tools; libraries that enhance output when a kernel is present; version drift, since newer Deno releases expose the jupyter namespace in all subcommands.
Related errors
- Illegal invocation
- No main module.
- Deno kernel already exists at {}, run again with `--force` t
- REPL thread error: {}
- REPL thread panicked
AI-assisted analysis of denoland/deno@a961cdec3b (2026-08-20).
Data as JSON: /api/errors/70128a8f96927fe9.
Report an issue: GitHub.