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
PascalCase / legacy schema files load as an empty schema reported as a successful migration; saving from the editor then wipes the file #278
SchemaSerializer only reads camelCase property names (Schema/SchemaSerializer.cs:16-26). It sets PropertyNamingPolicy = CamelCase, does not set PropertyNameCaseInsensitive, and does not reject unmapped members. So every key in a document written with Classes, Enums, Name, Members, ... is silently ignored.
Such a file also has no formatVersion, so Load treats it as version 0 and returns Status = Success with Message = "Migrated from format version 0 to 7." (SchemaSerializer.cs:~181-203). The resulting schema has 0 classes, 0 enums and 0 validation issues.
Reproduction
Every file under samples/legacy/** (26 files: the repository's own Carbon Monoxide and Dungeoneer schemas) produces this:
varr=SchemaSerializer.Load(File.ReadAllText("samples/legacy/dungeoneer/weapon.schema.json"));// Success | Migrated from format version 0 to 7. | classes=0 enums=0 issues=0
A hand-written { "Classes": [ { "Name": "A", ... } ] } behaves the same way.
Consequences
kschema validate old.schema.json prints 0 error(s), 0 warning(s) and exits 0.
kschema generate reports "declares no code generators" rather than saying the file wasn't understood.
In the editor (Schema.Editor/SchemaEditor.Files.cs, LoadFrom), the file opens as an empty document with no message. Any edit followed by Save overwrites the original with an empty schema, and the data is lost.
docs/schema-format.md:708-709 says "No version field - treat it as version 0 and migrate. Files written before versioning are still readable and always will be." For these files that promise is broken.
Not supporting the legacy dialect is deliberate (samples/README.md; LegacySchemaReader lives in the tests). Loading it as an empty success is not.
Suggested fix
Refuse a document whose root has properties the model doesn't recognise. Either set JsonUnmappedMemberHandling.Disallow on Schema, or pre-check the known root keys in ReadFormatVersion. Return SchemaLoadStatus.InvalidJson with a message that names the key, e.g. "unrecognised property 'Classes' — property names are camelCase".
Or set PropertyNameCaseInsensitive = true, so that casing alone never drops data.
Either way, add a test that loading samples/legacy/dungeoneer/weapon.schema.json through SchemaSerializer.Load does not succeed with an empty schema.
Priority: High. A PascalCase or legacy file loads as an empty schema reported as a successful migration. validate passes, and saving from the editor overwrites the user's file with an empty schema. All 26 samples/legacy/** files reproduce it.
Area / suggested assignment: Schema SchemaSerializer (load / migration), plus the editor's save path.
Next step: Refuse unmapped root properties with InvalidJson, and give a message naming the key (preferred over silently accepting any casing). Add the weapon.schema.json regression test. Optionally, have the editor refuse to save over a file that loaded with errors.
Activity
matt-edmondson commentedon Oct 17, 2026
Triage
validatepasses, and saving from the editor overwrites the user's file with an empty schema. All 26samples/legacy/**files reproduce it.SchemaSerializer(load / migration), plus the editor's save path.InvalidJson, and give a message naming the key (preferred over silently accepting any casing). Add theweapon.schema.jsonregression test. Optionally, have the editor refuse to save over a file that loaded with errors.Generated by Claude Code
Refuse schema documents with root properties the model does not read