halo-dev/halo · error · SchemaViolationException
Failed to validate {gvk}
Error message
Failed to validate {gvk} What it means
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.
Source
Thrown at application/src/main/java/run/halo/app/extension/JSONExtensionConverter.java:82
var scheme = schemeManager.get(gvk);
try {
var convertedExtension = Optional.of(extension)
.map(item -> scheme.type().isAssignableFrom(item.getClass())
? item
: objectMapper.convertValue(item, scheme.type()))
.orElseThrow();
var validation = new ValidationData<>(extension);
var extensionJsonNode = objectMapper.valueToTree(convertedExtension);
var validator = getValidator(scheme);
validator.validate(extensionJsonNode, validation);
if (!validation.isValid()) {
log.debug(
"Failed to validate Extension: {}, and errors were: {}",
extension.getClass(),
validation.results());
throw new SchemaViolationException(extension.groupVersionKind(), validation.results());
}
var version = extension.getMetadata().getVersion();
var storeName = buildStoreName(scheme, extension.getMetadata().getName());
var data = objectMapper.writeValueAsBytes(extensionJsonNode);
return new ExtensionStore(storeName, data, version);
} catch (IOException e) {
throw new ExtensionConvertException("Failed write Extension as bytes", e);
} catch (ResolutionException e) {
throw new RuntimeException("Failed to create schema validator", e);
}
}
@Override
public <E extends Extension> E convertFrom(Class<E> type, ExtensionStore extensionStore) {
try {
var extension = objectMapper.readValue(extensionStore.getData(), type);
extension.getMetadata().setVersion(extensionStore.getVersion());View on GitHub (pinned to d2f5165f9c)
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.
Example fix
// before: extension missing required spec field -> SchemaViolationException // after: populate spec per the Scheme schema, then client.create(extension)
Defensive patterns
Strategy: try-catch
Validate before calling
// validate the extension JSON against its Scheme schema before create
var validator = scheme.getSchemaValidator();
var node = objectMapper.valueToTree(extension);
var result = new ValidationData<>(extension);
validator.validate(node, result);
if (!result.isValid()) {
throw new IllegalArgumentException("Schema invalid: " + result.results());
} Try / catch
// inspect ValidationResults and surface the failing paths
try {
client.create(extension);
} catch (SchemaViolationException e) {
log.warn("Schema errors for {}: {}",
extension.groupVersionKind(), e.getErrors());
fixAndRetry(e.getErrors());
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Unexpected APIVersion string: {}
- Invalid file type, only jar is supported
- validation.error.email.pattern
- Name is required
- Email is required
AI-assisted analysis of halo-dev/halo@d2f5165f9c (2026-08-14).
Data as JSON: /api/errors/abee43f205edf3cd.
Report an issue: GitHub.