{"record":{"id":"abee43f205edf3cd","repo":"halo-dev/halo","slug":"failed-to-validate-gvk","errorCode":null,"errorMessage":"Failed to validate {gvk}","messagePattern":"Failed to validate (.+?)","errorType":"validation","errorClass":"SchemaViolationException","httpStatus":400,"severity":"error","filePath":"application/src/main/java/run/halo/app/extension/JSONExtensionConverter.java","lineNumber":82,"sourceCode":"        var scheme = schemeManager.get(gvk);\n\n        try {\n            var convertedExtension = Optional.of(extension)\n                    .map(item -> scheme.type().isAssignableFrom(item.getClass())\n                            ? item\n                            : objectMapper.convertValue(item, scheme.type()))\n                    .orElseThrow();\n            var validation = new ValidationData<>(extension);\n\n            var extensionJsonNode = objectMapper.valueToTree(convertedExtension);\n            var validator = getValidator(scheme);\n            validator.validate(extensionJsonNode, validation);\n            if (!validation.isValid()) {\n                log.debug(\n                        \"Failed to validate Extension: {}, and errors were: {}\",\n                        extension.getClass(),\n                        validation.results());\n                throw new SchemaViolationException(extension.groupVersionKind(), validation.results());\n            }\n\n            var version = extension.getMetadata().getVersion();\n            var storeName = buildStoreName(scheme, extension.getMetadata().getName());\n            var data = objectMapper.writeValueAsBytes(extensionJsonNode);\n            return new ExtensionStore(storeName, data, version);\n        } catch (IOException e) {\n            throw new ExtensionConvertException(\"Failed write Extension as bytes\", e);\n        } catch (ResolutionException e) {\n            throw new RuntimeException(\"Failed to create schema validator\", e);\n        }\n    }\n\n    @Override\n    public <E extends Extension> E convertFrom(Class<E> type, ExtensionStore extensionStore) {\n        try {\n            var extension = objectMapper.readValue(extensionStore.getData(), type);\n            extension.getMetadata().setVersion(extensionStore.getVersion());","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/halo-dev/halo/blob/d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8/application/src/main/java/run/halo/app/extension/JSONExtensionConverter.java#L64-L100","documentation":"Thrown as a SchemaViolationException (HTTP 400) by JSONExtensionConverter.convertTo when the JSON serialization of an Extension fails the OpenAPI schema validator attached to its Scheme. The message is 'Failed to validate ' + groupVersionKind, and the exception carries the full ValidationResults so callers can inspect which fields failed. It occurs on create/update paths before persisting to the ExtensionStore.","triggerScenarios":"client.create/update on any Extension (custom or built-in) whose JSON violates the registered Scheme's schema — required fields missing, wrong types, enum violations, pattern mismatches, or extra fields rejected by additionalProperties. Triggered whenever convertTo runs (create, update, and some internal writes).","commonSituations":"Custom extension model added/changed but Scheme/schema not regenerated; client (plugin or API caller) sends a field with the wrong type or omits a required field; GVK mismatch; OpenAPI schema drift after a version bump; manually constructed Unstructured with invalid shapes.","solutions":["Inspect exception.getErrors() (ValidationResults) to find the exact failing schema paths and fix the offending fields.","Regenerate the extension's OpenAPI schema / re-register the Scheme after model changes so validation matches the new contract.","Send a payload that matches the declared schema: correct types, all required fields, valid enum/pattern values.","Validate the JSON against the Scheme's schema on the client side before calling create/update."],"exampleFix":"// before: extension missing required spec field -> SchemaViolationException\n// after:  populate spec per the Scheme schema, then client.create(extension)","handlingStrategy":"try-catch","validationCode":"// validate the extension JSON against its Scheme schema before create\nvar validator = scheme.getSchemaValidator();\nvar node = objectMapper.valueToTree(extension);\nvar result = new ValidationData<>(extension);\nvalidator.validate(node, result);\nif (!result.isValid()) {\n    throw new IllegalArgumentException(\"Schema invalid: \" + result.results());\n}","typeGuard":null,"tryCatchPattern":"// inspect ValidationResults and surface the failing paths\ntry {\n    client.create(extension);\n} catch (SchemaViolationException e) {\n    log.warn(\"Schema errors for {}: {}\",\n        extension.groupVersionKind(), e.getErrors());\n    fixAndRetry(e.getErrors());\n}","preventionTips":["Regenerate the OpenAPI schema / re-register the Scheme after any extension model change.","Keep the client payload in sync with the declared schema (types, required fields, enums).","Run schema validation in tests for every create/update path."],"tags":["extension","schema","validation","openapi","webflux"],"backgroundTag":null,"analyzedSha":"d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8","analyzedAt":"2026-08-14T00:18:38.915Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}