OpenAPITools/openapi-generator · error · IllegalArgumentException

must be a valid…

Error message

{} must be a valid com.fasterxml.jackson.annotation.JsonInclude.Include value (ALWAYS, NON_NULL, NON_ABSENT, NON_EMPTY, NON_DEFAULT, USE_DEFAULTS, CUSTOM), or NONE to emit no annotation, but was: {}

What it means

JsonAnnotationPolicyUtils.resolveManualJsonIncludePolicy (used by the spring and kotlin-spring generators) validates a per-property 'x-jackson-json-include-policy' vendor extension from the spec. The value must be a Jackson JsonInclude.Include constant — ALWAYS, NON_NULL, NON_ABSENT, NON_EMPTY, NON_DEFAULT, USE_DEFAULTS, CUSTOM — or NONE/blank meaning 'emit no annotation'. Anything else throws IllegalArgumentException, with the extension name prefixed so you know where to look.

Solutions

  1. Use an exact JsonInclude.Include enum name in the spec: NON_NULL, NON_EMPTY, NON_DEFAULT, ALWAYS, NON_ABSENT, USE_DEFAULTS, CUSTOM (underscores, case-insensitive).
  2. Use NONE or an empty value when you want no @JsonInclude emitted for that property.
  3. Search your spec for x-jackson-json-include-policy and validate each occurrence against the enum list in the error message.

Example fix

# before (openapi.yaml)
components:
  schemas:
    User:
      properties:
        email:
          type: string
          x-jackson-json-include-policy: non-null

# after
          x-jackson-json-include-policy: NON_NULL
Defensive patterns

Strategy: validation

Validate before calling

// Node: validate x-jackson-json-include-policy values in the spec
const ALLOWED = new Set(['ALWAYS','NON_NULL','NON_ABSENT','NON_EMPTY','NON_DEFAULT','USE_DEFAULTS','CUSTOM','NONE','']);
const check = (o) => { for (const [k, v] of Object.entries(o ?? {})) {
  if (k === 'x-jackson-json-include-policy' && !ALLOWED.has(String(v).trim().toUpperCase()))
    throw new Error(`invalid x-jackson-json-include-policy: ${v}`);
  if (v && typeof v === 'object') check(v);
}};
check(require('./openapi.json'));

Type guard

const JSON_INCLUDE_POLICIES = ['ALWAYS','NON_NULL','NON_ABSENT','NON_EMPTY','NON_DEFAULT','USE_DEFAULTS','CUSTOM','NONE'] as const;
type JsonIncludePolicy = typeof JSON_INCLUDE_POLICIES[number];
const isJsonIncludePolicy = (v: unknown): v is JsonIncludePolicy =>
  typeof v === 'string' &&
  (JSON_INCLUDE_POLICIES as readonly string[]).includes(v.trim().toUpperCase());

Try / catch

catch (IllegalArgumentException e) {
    // message names the extension and the bad value — fix the spec and regenerate
    throw new RuntimeException("Spec fix needed: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Adding x-jackson-json-include-policy: non-null (hyphen instead of underscore), if_present, or NEVER to a schema property in the OpenAPI spec and generating with -g spring or -g kotlin-spring. Values are matched case-insensitively after trim, but only exact enum names parse.

Common situations: Writing Jackson annotation values from memory with hyphens or wrong casing of words ('non-null', 'use-defaults'); copying Jackson 2.x vs 3.x enum names; a misspelled extension value silently present in a large spec until generation fails.

Related errors


AI-assisted analysis of OpenAPITools/openapi-generator@fcec517be3 (2026-08-22). Data as JSON: /api/errors/a776336ac3fac048. Report an issue: GitHub.

Appendix: source

Thrown at modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/JsonAnnotationPolicyUtils.java:84

    private JsonAnnotationPolicyUtils() {
    }

    /**
     * Validate and normalize a manual per-property {@code x-jackson-json-include-policy} override.
     *
     * @param rawPolicy       the raw vendor extension value set directly on the property in the spec
     * @param extensionName   the vendor extension key, used in the error message (kept generator-agnostic)
     * @return the normalized (upper-case) policy name to emit, or {@code null} when the override means
     * "emit no annotation" ({@code NONE}/blank), in which case the caller must drop the extension.
     * @throws IllegalArgumentException when the override is not a valid {@code JsonInclude.Include} value.
     */
    public static String resolveManualJsonIncludePolicy(Object rawPolicy, String extensionName) {
        JsonIncludePolicy parsed;
        try {
            parsed = JsonIncludePolicy.parse(rawPolicy);
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException(extensionName
                    + " must be a valid com.fasterxml.jackson.annotation.JsonInclude.Include value "
                    + "(ALWAYS, NON_NULL, NON_ABSENT, NON_EMPTY, NON_DEFAULT, USE_DEFAULTS, CUSTOM), or NONE to emit "
                    + "no annotation, but was: " + rawPolicy);
        }
        if (parsed == null || !parsed.isEmitted()) {
            return null;
        }
        return parsed.name();
    }

    /**
     * Validate and normalize the {@code optionalNonNullPropertyJsonInclude} config option value.
     *
     * @param policy      the raw config option value (may be {@code null}, in which case the default
     *                    {@code NON_NULL} is returned)
     * @param optionName  the config option name, used in the error message (kept generator-agnostic)
     * @return the normalized (upper-case) policy name: one of {@code NON_NULL}, {@code NON_EMPTY},
     * {@code NON_DEFAULT}, {@code NONE}.

View on GitHub (pinned to fcec517be3)