glTF validation errors, decoded
The Khronos glTF-Validator is precise and unfriendly. Its messages are accurate descriptions of a spec violation and terrible descriptions of what you did wrong. Here is the translation.
Last reviewed July 27, 2026
Severities are not all equal
The validator grades issues as Error, Warning, Information and Hint. Errors are spec violations — a conforming viewer is entitled to refuse your file, and some will. Warnings are legal but portability-hostile: the file loads, and different runtimes may disagree about what it looks like. Information and Hint are advisory.
A useful triage rule: fix every Error before shipping, read every Warning and make a decision about it, and skim the rest. The full code list is published in the validator repository.
Geometry and accessor errors
| Code | What it means | Fix |
|---|---|---|
ACCESSOR_INDEX_OOB | An index buffer references a vertex that does not exist ("greater than the maximum vertex index available"). | The exporter wrote indices and vertices out of sync. Re-export; if it persists, the mesh was likely edited after indexing. |
ACCESSOR_MIN_MISMATCH / ACCESSOR_MAX_MISMATCH | The declared min/max on an accessor does not match the actual data. | Recompute bounds. Common after a tool edits vertex data in place without updating the accessor. |
MESH_PRIMITIVE_POSITION_ACCESSOR_WITHOUT_BOUNDS | accessor.min and accessor.max are required on POSITION and are missing. | Frustum culling and camera framing depend on these. Regenerate with a compliant exporter. |
MESH_PRIMITIVE_UNEQUAL_ACCESSOR_COUNT | Attributes of one primitive disagree on vertex count. | Usually a partially-applied edit — for example UVs added to some vertices only. |
ACCESSOR_VECTOR3_NON_UNIT | A normal or tangent vector is not unit length. | Normalize normals on export. Non-unit normals produce lighting that drifts across the surface. |
ACCESSOR_INVALID_FLOAT | An accessor contains NaN or Infinity. | Degenerate geometry upstream. Find and delete the offending vertices; do not paper over it. |
MESH_PRIMITIVE_ACCESSOR_UNALIGNED | "Vertex attribute data must be aligned to 4-byte boundaries." | A buffer-packing bug in whatever wrote the file. Re-serialize with a maintained library. |
The tangent-space pair
Two codes that look similar and are not. MESH_PRIMITIVE_GENERATED_TANGENT_SPACE is a Warning: "Material requires a tangent space but the mesh primitive does not provide it. Runtime-generated tangent space may be non-portable across implementations." Your normal map works, but each renderer derives tangents its own way, so the surface detail differs between your DCC, three.js and Quick Look.
MESH_PRIMITIVE_NO_TANGENT_SPACE is an Error: the material needs a tangent space and there is no normal map from which to derive one. That is an inconsistent material, not a missing attribute.
The fix for the warning is to export tangents. The fix for the error is to correct the material.
Material and texture issues
| Code | What it means | Fix |
|---|---|---|
MESH_PRIMITIVE_TOO_FEW_TEXCOORDS | A texture binding references a TEXCOORD_n the mesh does not have. | Either add the UV set or repoint the texture at TEXCOORD_0. Common when a lightmap UV is stripped. |
TEXTURE_INVALID_IMAGE_MIME_TYPE | The image MIME type is not one glTF core allows. | Core glTF permits PNG and JPEG. WebP and KTX2 need EXT_texture_webp / KHR_texture_basisu declared. |
IMAGE_MIME_TYPE_INVALID | "Recognized image format does not match declared image format." | A JPEG labelled image/png or similar. Fix the declaration, not the image. |
IMAGE_NPOT_DIMENSIONS | Information only: non-power-of-two image dimensions. | Legal, but blocks clean mipmapping and block compression. Worth fixing before a KTX2 pass. |
MATERIAL_ALPHA_CUTOFF_INVALID_MODE | alphaCutoff set on a material whose alpha mode is not MASK. | Harmless but indicates a confused export. Set alphaMode correctly. |
Extension errors
UNDECLARED_EXTENSION(Error) — an extension is used but missing fromextensionsUsed. Almost always a hand-edited or programmatically-assembled glTF.NON_REQUIRED_EXTENSION(Error) — "Extension cannot be optional." Some extensions change geometry or texture decoding so fundamentally that a viewer which ignores them gets nothing usable; those must appear inextensionsRequired.UNSUPPORTED_EXTENSION(Information) — the validator does not know this extension, so it cannot check it. Not a defect in your file.MULTIPLE_EXTENSIONS(Warning) — two extensions on the same object may be incompatible. Worth a look.
Skinning and animation
The skinning warnings surprise people because they describe a rule of the format rather than a defect: transforms on a skinned mesh node are ignored. NODE_SKINNED_MESH_LOCAL_TRANSFORMS and NODE_SKINNED_MESH_PARENT_TRANSFORMS are telling you that a transform you authored will have no effect at runtime — so if the model looks misplaced, moving that node will not help. Bake the transform into the joints instead.
Also common: ACCESSOR_WEIGHTS_NON_NORMALIZED (skin weights per vertex must sum to 1), ROTATION_NON_UNIT (rotation quaternions must be normalized), and ANIMATION_CHANNEL_TARGET_NODE_MATRIX (a channel cannot animate TRS on a node defined with a matrix — decompose it).
GLB container errors
If you see GLB_INVALID_MAGIC, GLB_LENGTH_MISMATCH, GLB_UNEXPECTED_FIRST_CHUNK ("First chunk must be of JSON type") or GLB_CHUNK_LENGTH_UNALIGNED, stop debugging your model — the container itself is malformed. Something truncated the file, concatenated it wrongly, or wrote chunk headers by hand. Re-export or re-download.
The advisory codes worth reading anyway
UNUSED_OBJECT— dead weight in the file. Prune it.ACCESSOR_INDEX_TRIANGLE_DEGENERATE— zero-area triangles. Harmless individually, a sign of sloppy topology in bulk.NODE_EMPTY— empty nodes. Fine as anchors, otherwise noise.BUFFER_VIEW_TARGET_MISSING— a Hint, but settingtargethelps some loaders bind buffers efficiently.
Validation is necessary and not sufficient
A file can pass the validator with zero issues and still be unusable in commerce: 4 million triangles, 4K textures on a thumbnail, glass authored with an extension USDZ cannot represent, UV islands packed too tightly to survive block compression, an origin floating in mid-air. The validator checks conformance to glTF 2.0. It does not check whether your asset is fit for a product page — that is the pre-publish checklist, and for AR specifically, what Quick Look needs.
Common questions
- What does ACCESSOR_INDEX_OOB mean?
- An index in the index buffer points at a vertex that does not exist — its value exceeds the maximum available vertex index. It almost always means the exporter wrote indices and vertex data out of sync, so re-exporting from the source is the fix.
- Should I fix glTF validator warnings or only errors?
- Fix all Errors — they are spec violations and some viewers will refuse the file. Read every Warning and make a deliberate decision: warnings usually mean the file loads but different runtimes may render it differently, which is exactly the class of bug that shows up only in production.
- Why do I get a tangent space warning when my model has a normal map?
- Because the mesh has no TANGENT attribute, so the runtime must generate one. The validator flags this as potentially non-portable: each renderer derives tangents differently, so your surface detail can look different in three.js, your DCC and AR Quick Look. Export tangents to remove the ambiguity.
- Are non-power-of-two textures an error?
- No, the validator reports IMAGE_NPOT_DIMENSIONS as Information only. But NPOT textures cannot be block-compressed into KTX2 without padding, and their mip chains behave poorly on some mobile GPUs, so power-of-two dimensions are still the right default.
Reading about it is slower than measuring it. Drop your .glb, .gltf, or .usdz in and get every blocker on this page checked against the real bytes — packaging, textures, geometry, AR parity — with the fix for each one.