Khronos glTF Validator report format, sample-asset corpus and extension prefix registry as a conformance kit
Document status:
reviewed. Canonical source.
Summary
The Khronos glTF ecosystem pairs a specification with three executable conformance artifacts. The glTF Validator (Dart, Apache-2.0) checks JSON schema conformance, reference validity, binary buffer contents, images, GLB container structure and a set of extensions, and writes a JSON report described by docs/validation.schema.json: uri, mimeType, validatorVersion, validatedAt, an issues block with counts (numErrors, numWarnings, numInfos, numHints), a truncated flag and messages each carrying code, severity (0 Error, 1 Warning, 2 Information, 3 Hint), message and either a JSON pointer or a GLB byte offset, plus an info block. ISSUES.md enumerates 159 codes across six categories (IoError, SchemaError, SemanticError, LinkError, DataError, GlbError). Unknown extensions are Information (UNSUPPORTED_EXTENSION), undeclared use is an Error (UNDECLARED_EXTENSION), and unknown properties are Warnings (UNEXPECTED_PROPERTY).
glTF-Sample-Assets is “a curated collection of glTF models that illustrate one or more features or capabilities of glTF”; each model has metadata.json (name, path, summary, tags, legal with SPDX license, screenshot) and is indexed in Models/model-index.json with tags core, extension, testing, showcase, video, written, pbrtest, issues and format variants (glTF, glTF-Binary, glTF-Embedded, glTF-Draco, glTF-Quantized, glTF-KTX-BasisU). CI runs the validator over every asset. The extension registry defines prefixes (KHR reserved for Khronos, EXT for multi-vendor, 99 registered vendor prefixes obtained by GitHub issue), naming rules, a five-stage status ladder (Proposal, Initial Draft, Review Draft, Release Candidate, Ratified) and the rule that extensions “can’t remove existing glTF properties or redefine existing glTF properties”.
Evidence
- Report schema:
uri,mimeType(model/gltf+jsonormodel/gltf-binary),validatorVersion(semver),validatedAt(date-time),issues.{numErrors,numWarnings,numInfos,numHints,messages,truncated}, messageseverityenum 0–3 with descriptions Error/Warning/Information/Hint,pointer(json-pointer) oroffsetrequired — https://github.com/KhronosGroup/glTF-Validator/blob/main/docs/validation.schema.json (retrieved 2026-08-29). - CLI: report written to
<asset_filename>.report.json, recursive directory validation, “Shell return code will be non-zero if at least one error was found”; options-o/--stdout,-r/--validate-resources,-t/--write-timestamp,-p/--absolute-path,-m/--messages,-a/--all,-c/--config,-h/--threads—README.md(main). - Config file:
max-issues,ignorelist,onlylist,overrideseverity map with “0 - Error, 1 - Warning, 2 - Info, 3 - Hint” —docs/config-example.yaml. - Implemented feature classes: JSON syntax and GLB correctness, schema properties, reference validity, Data URI, accessor values (NaN, invalid quaternions, indecomposable matrices),
accessor.min/max, sparse accessors, animation I/O, image NPOT and unsupported features, extension validation forEXT_texture_webp,KHR_animation_pointer(partial),KHR_lights_punctual,KHR_materials_anisotropy, … —README.md“Implemented features”. - Issue table: 159 codes; category sizes IoError 1, SchemaError 14, SemanticError 41, LinkError 52, DataError 35, GlbError 16 —
ISSUES.md(main, retrieved 2026-08-29). - Specific codes:
UNEXPECTED_PROPERTYWarning (line 20),INVALID_EXTENSION_NAME_FORMATWarning (42),NON_RELATIVE_URIWarning (73),UNKNOWN_ASSET_MAJOR_VERSIONError /UNKNOWN_ASSET_MINOR_VERSIONWarning (78–79),INCOMPLETE_EXTENSION_SUPPORTInformation (102),UNDECLARED_EXTENSIONError (128),UNEXPECTED_EXTENSION_OBJECTError (129),UNSUPPORTED_EXTENSIONInformation (131),UNUSED_OBJECTInformation (134) —ISSUES.md. - Validator test corpus:
test/base/data/<category>/<case>.gltfpaired with<case>.gltf.report.jsongolden reports (e.g.accessor/alignment.gltf.report.json,custom_property.gltf.report.json); categories accessor, animation, asset, buffer, buffer_view, camera, glb, image, json, material, mesh, node, root, sampler, scene, skin, texture and_datavariants;test/extfor extensions — repository listing (retrieved 2026-08-29). - Latest tags
2.0.0-dev.3.10,2.0.0-dev.3.8,2.0.0-dev.3.7; distribution via npmgltf-validator, hosted drag-and-drop tool at https://github.khronos.org/glTF-Validator —README.md, tags list. - Sample assets purpose and lists: Showcase, Complete, Testing (“intended to be used for testing of viewers, converts, and other software systems”), Core Only, Video Tutorials, Written Tutorials, PBR tests, Issues — https://github.com/KhronosGroup/glTF-Sample-Assets/blob/main/README.md (retrieved 2026-08-29).
- Provided forms: separate-resource
.gltf, embedded Data URI (to be avoided except for specific cases), binary.glb— same README, “Model Contents”. Models/model-index.jsonentries withlabel,name,screenshot,tags,variants(e.g.ABeautifulGamewithglTF,glTF-Binary,glTF-Binary-KTX-ETC1S-Draco;AlphaBlendModeTesttaggedcore,testing) — file head (retrieved 2026-08-29); 162 model directories underModels/(listing).- Per-model
metadata.jsonwithversion: 2,legal[](license, licenseUrl, artist, year, owner, what, spdx),tags,screenshot,name,path,summary,createReadme—Models/Box/metadata.json,Models/NegativeScaleTest/metadata.json. - Sample-assets CI installs validator 2.0.0-dev.3.10 and runs
./gltf_validator -r -a ./Models/, uploading**/*.report.json—.github/workflows/ci.ymllines 1–30. - The archived glTF-Sample-Models repository was replaced; unlicensed assets removed;
2.0renamedModels— sample-assets README “Obsolete Interface”. - Prefix registry:
KHRandEXTreserved; 99 registered vendor prefixes (ADOBE, AGI, AMZN, BLENDER, CESIUM, EPIC, GODOT, GOOGLE, MSFT, NV, OMI, UNITY, VRMC, …); request “by submitting an issue on GitHub” with prefix and vendor name — https://github.com/KhronosGroup/glTF/blob/main/extensions/Prefixes.md andextensions/README.mdlines 117–121 (retrieved 2026-08-29). - Naming rules: uppercase prefix plus underscore, lowercase snake-case, recommended
<PREFIX>_<scope>_<feature>—extensions/README.mdlines 184–191. - Status ladder table (Proposal, Initial Draft, Review Draft, Release Candidate, Ratified); Review Draft requires “At least one third party glTF implementation”; Release Candidate requires Sample Viewer and Validator support —
extensions/README.mdlines 66–75. - “Extensions can’t remove existing glTF properties or redefine existing glTF properties to mean something else”;
extensionsUsedvsextensionsRequired; required iff “a typical glTF loader would fail to load the asset in the absence of support” —extensions/README.mdlines 131–175. - Extension schemas “should allow additional properties”;
extrasis the application-specific escape hatch distinct from extensions —extensions/README.mdlines 178–215. - Current in-progress KHR list includes
KHR_interactivity(Release Candidate),KHR_gaussian_splatting(Release Candidate),KHR_texture_procedurals(Initial Draft) —extensions/README.mdlines 45–57.
Mechanism
The validator is a single-pass structural checker followed by link and data passes. Schema errors come from the JSON Schema of the core spec; semantic errors from cross-field constraints; link errors from index references between arrays (accessor → bufferView → buffer, node → mesh, …); data errors from decoding buffers and images; GLB errors from container parsing. Every finding is a coded issue with a fixed severity and a locator (JSON pointer for the JSON tree, byte offset for GLB). Severities are policy, not structure: a YAML config can override any code’s severity, ignore codes, or restrict to a subset, and a max-issues cap sets truncated. The exit code depends only on error count, so warnings never break a pipeline unless overridden to errors.
Extension handling encodes the ecosystem’s preservation contract. Any extension object must be declared in extensionsUsed (else Error). An extension the validator does not implement is reported as Information, not failure, so vendor extensions pass validation by default; partially implemented extensions are flagged as INCOMPLETE_EXTENSION_SUPPORT. Unknown properties outside extensions/extras are Warnings. This makes “opaque but declared” the validated state, and “opaque and undeclared” the failing state.
The test corpus is golden-report based: every input asset has a checked-in expected report, so validator changes are detected as report diffs. The sample-asset corpus is separately tagged by purpose; the testing tag marks assets that exercise a feature edge (alpha modes, negative scale, NPOT textures) and the core tag marks assets that need no extension. CI validates the entire corpus, and the extension status ladder requires validator and sample-viewer support before Release Candidate, closing the loop between spec, corpus and checker.
Prefix registration is deliberately lightweight: a GitHub issue reserves a namespace, and promotion from vendor to EXT requires multiple implementations while KHR requires Khronos ratification and IP coverage. Naming rules make ownership and scope parseable from the identifier.
NUIF relevance
Borrow
- Publish a JSON Schema for NUIF
validateoutput with counts per severity,truncated, coded messages, and a locator (entity/property path or byte offset for binary profiles), mirroringvalidation.schema.json. - Maintain a single issue-code table with fixed default severities and categories (schema, semantic, link, data, container), and require every diagnostic to cite a code.
- Make severity policy configurable (ignore, only, override, max-issues) while keeping exit status defined by error count, as the validator does.
- Treat “unknown but declared extension” as Information and “undeclared extension object” as Error, which is the executable form of NUIF’s used/required rule.
- Build the conformance fixture corpus with per-asset
metadata.json(SPDX license, tags, summary, variants) and a generated index; tag fixturescore,extension,testing,issues. - Store golden validation reports alongside fixtures so validator regressions surface as diffs.
- Adapt the prefix registry model to NUIF’s lowercase identifier grammar (
nuif.*,ext.*, collision-resistant vendor namespaces) and adopt the status ladder that requires validator and reference-viewer support before ratification.
Adapt
- glTF’s locator is a JSON pointer, which is path-based; NUIF locators must use stable semantic IDs with an optional path hint since NUIF identity is path-independent.
- The validator does not check preservation across a round trip; NUIF conformance must add a preservation suite (import → export → compare) that the glTF kit lacks.
- Format variants (
glTF-Binary,glTF-Embedded, …) map to NUIF profiles (nuif-text-0,nuif-cbor-0, package); NUIF should require every fixture in every profile with canonical-hash equality. extrasas an untyped escape hatch conflicts with NUIF’s requirement that extension data be namespaced; NUIF should route such data through a vendor extension instead.
Reject
- Dart as an implementation language is irrelevant; NUIF’s validator is the Rust CLI.
- Severity-only categorization without fidelity classes is insufficient; NUIF diagnostics must also carry the fidelity class (
lossless…unsupported) and the responsible pass. - The sample corpus’s mixed CC-BY/CC0 licensing complicates redistribution in test suites; NUIF fixtures should be CC0 or project-licensed.
Open questions
- Whether NUIF should reserve numeric severity values (0–3) for compatibility with tooling that consumes glTF-style reports.
- How to represent multi-profile locators (text line/column, CBOR byte offset, semantic ID) in one report entry without ambiguity.
- Whether the validator’s “unsupported extension is Information” default is safe for NUIF where an unrenderable required extension must be a conformance failure at render time but not at parse time.
- How NUIF’s extension status ladder should handle dialects that change lowering rules rather than add properties.