OpenAPITools/openapi-generator · error · IllegalArgumentException

{} must be one of [SKIP, FAIL] but was: {}

Error message

{} must be one of [SKIP, FAIL] but was: {}

What it means

JsonAnnotationPolicyUtils.normalizeJsonSetterNulls validates the spring/kotlin-spring option 'optionalNonNullPropertyJsonSetterNulls', which controls whether optional non-nullable properties get @JsonSetter(nulls = SKIP) (ignore explicit JSON nulls) or Nulls.FAIL (reject them). Only SKIP and FAIL are accepted — notably NONE is NOT valid here (it is reserved for the per-property extension), and a null/absent option simply skips normalization.

Source

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

    /**
     * Validate and normalize the {@code optionalNonNullPropertyJsonSetterNulls} config option value.
     *
     * @param value      the raw config option value
     * @param optionName the config option name, used in the error message
     * @return the normalized {@link JsonSetterNullsMode} ({@code SKIP} or {@code FAIL})
     * @throws IllegalArgumentException when the value is not {@code SKIP} or {@code FAIL}
     */
    public static JsonSetterNullsMode normalizeJsonSetterNulls(String value, String optionName) {
        JsonSetterNullsMode parsed = null;
        if (value != null) {
            try {
                parsed = JsonSetterNullsMode.valueOf(value.trim().toUpperCase(java.util.Locale.ROOT));
            } catch (IllegalArgumentException e) {
                parsed = null;
            }
        }
        if (parsed != JsonSetterNullsMode.SKIP && parsed != JsonSetterNullsMode.FAIL) {
            throw new IllegalArgumentException(optionName + " must be one of [SKIP, FAIL] but was: " + value);
        }
        return parsed;
    }

    /**
     * Read back the {@code optionalNonNullPropertyJsonSetterNulls} config option from
     * {@code additionalProperties}, validating/normalizing it via {@link #normalizeJsonSetterNulls}. Returns
     * {@code current} unchanged when the option was not present (i.e. the generator's existing/default value,
     * typically {@code null} = unset, is kept).
     *
     * @param additionalProperties the generator's additional properties map
     * @param current               the generator's current {@code optionalNonNullPropertyJsonSetterNulls} value
     * @return the resolved {@link JsonSetterNullsMode} ({@code null} when left unset)
     */
    public static JsonSetterNullsMode resolveOptionalNonNullPropertyJsonSetterNulls(Map<String, Object> additionalProperties, JsonSetterNullsMode current) {
        if (!additionalProperties.containsKey(CodegenConstants.OPTIONAL_NON_NULL_PROPERTY_JSON_SETTER_NULLS)) {
            return current;
        }

View on GitHub (pinned to fcec517be3)

Solutions

  1. Use exactly SKIP or FAIL.
  2. To turn the behavior off, remove the option entirely — when unset, the mode is derived from openApiNullable (true -> FAIL where supported, false -> SKIP).
  3. Per-property opt-out goes in the spec as x-jackson-json-setter-nulls: NONE instead.

Example fix

# before
openapi-generator-cli generate -g spring \
  -DoptionalNonNullPropertyJsonSetterNulls=NONE

# after
openapi-generator-cli generate -g spring
# omit the option, or use -DoptionalNonNullPropertyJsonSetterNulls=SKIP
Defensive patterns

Strategy: validation

Validate before calling

case "$(printf '%s' "$OPT_NONNULL_JSON_SETTER_NULLS" | tr '[:lower:]' '[:upper:]' | tr -d ' ')" in
  SKIP|FAIL|"") ;;
  *) echo "ERROR: optionalNonNullPropertyJsonSetterNulls must be SKIP or FAIL (omit it to disable)" >&2; exit 1;;
esac

Type guard

const isJsonSetterNullsOption = (v: string): v is 'SKIP' | 'FAIL' =>
  ['SKIP', 'FAIL'].includes(v.trim().toUpperCase());

Prevention

When it happens

Trigger: Generating with -DoptionalNonNullPropertyJsonSetterNulls=NONE (common mistake — NONE looks like a safe 'off' value), =skip_nulls, or any other string. valueOf runs on the trimmed uppercase value, so 'skip' works but 'Skip nulls' does not.

Common situations: Trying to disable the feature by passing NONE (it is invalid for the option — just leave it unset); translating Jackson's Nulls.SKIP/FAIL docs into option values with extra words; sharing one options bundle between spring and kotlin-spring builds.

Related errors


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