What notebook metadata from Colab, JupyterLab, and VS Code actually means
Kernelspec, language_info, cell ids, and editor keys are notes about the last editor. They are not the packages, the data, or a promise the file will run.
Updated

Colab, JupyterLab, VS Code, and PyCharm all save a notebook as the same kind of JSON, then each one writes its own notes into metadata. Those notes explain the last editor. They do not install a kernel, pin packages, or tell you whether the outputs are still true.
What an .ipynb file contains lists the top-level fields. This page is the part that changes when the same analysis moves between editors and still fails to run on a second computer.

The two fields every modern notebook has
metadata.kernelspec is the kernel the author selected. You will usually see three strings:
name, a short id such aspython3or a conda env namedisplay_name, the label in the UI, such asPython 3orPython (course-env)language, almost alwayspython
Jupyter looks up name in the kernels installed on that machine (jupyter kernelspec list). If the name was conda-env-lab-py and the other computer has no kernel by that name, Jupyter says the kernel is missing. The notebook file is fine. The environment is not in the file.
metadata.language_info is a description of the language: name, sometimes version, mimetype, file_extension, and the lexer the editor used for highlighting. A version of 3.11.6 means the frontend recorded that string. It is not a lock. A machine with 3.12 can open the notebook. Code that depended on a 3.11-only behavior can then fail, and the metadata will not warn you in advance.
What Colab adds
A notebook downloaded from Google Colab usually has a metadata.colab object. It often includes a provenance list and sometimes notes about the runtime, the table of contents, or collapsed sections. Cell metadata may also carry Colab-specific keys.
None of that is the list of pip packages from the Colab VM. Colab’s kernel name in kernelspec is typically just python3. When you open that file on a laptop, Jupyter will start whatever local kernel is registered as python3, which may be older, newer, or missing the libraries the Colab cell imported.
If a Colab cell ran !pip install something or apt commands, those lines may be in source. They are shell commands, not a solved environment. They also do not run when a viewer or a converter opens the file.
What JupyterLab and VS Code add
JupyterLab, from nbformat 4.5 onward, writes a string id on each cell and sets nbformat_minor to at least 5. The id lets the interface track a cell when it is moved. Older notebooks omit ids and use a lower minor version. A missing id is not damage. A file that claims minor version 5 and has no ids is the inconsistent case, and a strict reader may complain. Repair can put ids back. It cannot know which cell used to have which id if they were never saved.
VS Code’s Jupyter extension often stamps code cells with metadata like vscode.languageId set to python. That tells the editor which highlighter to use. It does not select a virtualenv. The selected interpreter lives in VS Code’s own settings, outside the notebook, unless someone also wrote it into metadata by hand.
You may also see orig_nbformat after an upgrade from an older notebook, or a widgets object after ipywidgets ran. Unknown keys are supposed to be left alone. A tool that deletes every key it does not recognize will strip Colab provenance and widget state even when you only asked to change the title.
nbformat 3 is a different shape
Very old notebooks use nbformat 3. They store cells inside worksheets, not in a top-level cells array. Current Jupyter upgrades that shape when it opens the file. A converter that only looks for cells will say the file is empty or broken. If the JSON parses and nbformat is 3, the cells are probably under worksheets[0].cells. That is a version difference, not a truncated download.
What people expect metadata to contain
These are not in kernelspec or language_info, even when the notebook ran yesterday:
- The path to
python.exeor the virtualenv pip freezeoutput, unless the author printed it into a cell- Data files the code opened
- The Git commit of the project
- Whether the outputs match the source
Package names have to be read from the code. Requirements extraction looks at top-level import and from ... import lines in cell source and maps a few import names to the PyPI package people usually install. It does not read language_info.version, and it does not see a package that was imported only inside a function string or a shell command. A generated requirements.txt is a hint for the next environment, not a reproduction of the one that produced the outputs.
A practical check
Open the notebook in a text editor, or in the viewer, and answer four questions:
- Is
kernelspec.namea genericpython3, or a name that only exists on one computer? - Does
language_info.versionexist, and is it a version you actually have? - Is there a
colab,vscode, orwidgetsobject, and do you need it for the person receiving the file? - Do the import lines in the code match the environment you think this notebook needs?
If the kernel name is specific and the recipient does not have it, say which environment to create. The JSON will not say it for you. If the file will not even parse, that is a different problem from a missing kernel: metadata never gets read if the JSON is truncated. The format page covers that case.

