Conversation
A relation path carries URIs pointing at sub entities, but a key the data has as null was given [""] like any other missing value. That empty string is a reference to a sub entity that does not exist, so a consumer that follows it finds nothing: writing such entities to a JSON dataset aborts the whole write with "Current context not Array but Object", before a single entity is written. Reaching it needs one item of a list to carry the object and another to have it as null, which is ordinary in an API response - a GitLab query asking for the user who created a Terraform state version hits it as soon as one version was created by a job rather than a person. Only relations change. A plain path keeps its [""], which is what a dataset writes as an empty value. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A key's type is read off the values in the data, and two items can disagree
about it: one object carries an address and the next has it as null, or one
list is empty and the next holds objects. The type maps were merged with
`|`, so whichever item came last decided the schema.
That lost information in one of the two orders. A key seen as an object and
then as null ended up typed NoneType, which is not a relation, so the object
in the first item was flattened into its str() - the entity carried the text
{'city': 'San Francisco'} instead of a reference to a sub entity. The same
happened to a list of objects followed by an empty list. Reversing the two
items produced a different schema from the same kind of data.
The merge now keeps the type that says more: NoneType loses to anything, and
a bare list loses to a list of objects. Genuinely conflicting types, say str
against int, are still resolved by the last item seen, as before.
This changes the entities built from such data: a key that used to come out
as text now comes out as a relation with sub entities behind it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two defects in
build_entities_from_data, both reached by the same ordinary data: a keythat one item of a list carries as an object and another as null. Found while writing a
GraphQL response to a JSON dataset - a GitLab query asking for the user who created a
Terraform state version hits it as soon as one version was created by a job rather than a
person - and reproduced against a running deployment.
Each commit is one defect, and the second is the more invasive of the two, so it can be
dropped on its own if you would rather ship only the first.
1. A relation whose value is null got
[""]A relation path carries URIs pointing at sub entities, but a key the data has as null was
given
[""]like any other missing value. That empty string is a reference to a subentity that does not exist. A consumer that follows it finds nothing: writing such
entities to a JSON dataset aborts the whole write with
before a single entity is written. The path is now left empty instead. Only relations
change - a plain path keeps its
[""], which is what a dataset writes as an empty value.2. The type of a key was taken from the last item seen
The per-key type maps were merged with
|, so of two items that disagree about a key thelast one decided the schema. In one of the two orders that loses information:
[{"name": "sai", "address": {"city": "San Francisco"}}, {"name": "seebi", "address": None}]addressends up typedNoneType, which is not a relation, so the object in the firstitem is flattened into its
str()and the entity carries the text{'city': 'San Francisco'}instead of a reference. Reversing the two items produces adifferent schema from the same kind of data. A list of objects followed by an empty list
behaves the same way.
The merge now keeps the type that says more:
NoneTypeloses to anything, and a barelistloses to alist_dict. Genuinely conflicting types, saystragainstint, arestill resolved by the last item seen, as before.
This changes the entities built from such data: a key that used to come out as text
now comes out as a relation with sub entities behind it. That is the point of the fix, but
it is a shape change for anyone whose mapping consumed the flattened text.
Tests
Three regression tests, one per symptom - the null relation, the object followed by a
null, and the list of objects followed by an empty list. Each fails on
mainand passeshere; I checked by reverting the source with the tests in place.
task checkis green: ruff, mypy across 51 files, deptry, trivy, 55 passed 1 skipped.🤖 Generated with Claude Code