You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Valid .deepnote files are rejected when a block's content merely looks like a YAML anchor, alias or tag #571
I originally filed this as "YAML aliases are rejected, so support them on read". That was wrong twice over, and I want the wrong version on the record rather than quietly replaced:
The prohibition is deliberate and correct. validateYamlStructure in packages/blocks/src/deepnote-file/parse-yaml.ts rejects anchors, aliases, merge keys and custom tags with a dedicated ProhibitedYamlFeatureError, and parse-yaml.test.ts has a describe('anchor and alias rejection') suite covering each. Anchors and aliases are the billion-laughs expansion vector and tags are a deserialization vector; a parser reading synced files from a workspace should refuse all four.
So "support aliases on read" was actively bad advice and is withdrawn.
The other half of what I suggested — "reject them with a message that names the construct" — is already implemented. The message names the feature exactly.
The actual bug
validateYamlStructure runs as a regex over the raw text, before the document is parsed. It therefore cannot tell a YAML anchor from text that merely looks like one inside a block's content: scalar — and block content is arbitrary user text.
There is no anchor. The content is one literal string inside a block scalar.
Why this is reachable, not theoretical
The most likely way a real notebook contains &anchor is a markdown cell documenting a YAML config — CI, docker-compose, Kubernetes — which is exactly where anchors are idiomatic:
That notebook cannot be read. A notebook about YAML is the one thing this format cannot store.
The tag rule has the same shape and a wider blast radius, because key: !word is common in CSS, shell and config snippets:
- type: codecontent: |- flag: !important
Parse error: YAML tags are not allowed in Deepnote files: !important
Suggested direction
Validate the parsed document, not the raw text. parse-yaml.ts already calls parseDocument, and walking the resulting AST with visit distinguishes a real construct from text that resembles one. Verified against main:
Input
anchors
aliases
mergeKeys
tags
a: &x [1,2] / b: *x
["x"]
1
0
—
the same text inside a content: block scalar
[]
0
0
—
base: &b {x: 1} / <<: *b
["b"]
1
1
—
a: !mytag 5
—
—
—
["!mytag"]
flag: !important inside a content: block scalar
—
—
—
[]
The predicates that produce that, all from the yaml package:
Each one keeps the prohibition exactly as strict against the real construct while being blind to block content, which is where every false positive comes from.
Two caveats for whoever picks this up:
Do not relax the prohibition while fixing the false positives. The point is to reject real anchors more precisely, not fewer of them.
Parsing first means untrusted input reaches parseDocument before validation, so the expansion-bomb concern has to be handled separately. maxAliasCount is the lever, but note it applies at toJS(), not at parseDocument — doc.toJS({ maxAliasCount: 0 }) throws ReferenceError: Alias resolution is disabled, whereas passing it to parseDocument does nothing. (I checked this because my first draft of this issue asserted the opposite.) Building the document is bounded by input size; only resolution expands, so validating the AST before any toJS() call is safe, and maxAliasCount: 0 is the belt to the AST check's braces.
A line number in the message would also help, but the false positives are the part that loses data.
Why it matters beyond parsing
A rejected file is a project missing from anything that reads the synced tree. deepnote lint fails outright on it. The workspace-wide checks in #555–#560 report the count of unparseable files, so it is not fully silent there — but a false rejection means the corpus is smaller than it should be for a reason nobody would think to look for, and "we could not read 3 files" reads like a data problem rather than a bug in the reader.
changed the title [-].deepnote files using YAML aliases fail to parse, silently shrinking every workspace-wide check[/-][+]Valid .deepnote files are rejected when a block's content merely looks like a YAML anchor, alias or tag[/+]on Oct 8, 2026
Activity
[-].deepnote files using YAML aliases fail to parse, silently shrinking every workspace-wide check[/-][+]Valid .deepnote files are rejected when a block's content merely looks like a YAML anchor, alias or tag[/+]