hibernate/hibernate-orm · error · IllegalStateException

unexpected processing state: {}

Error message

unexpected processing state: {}

What it means

Every typed value accessor on JsonDocumentReader (getStringValue, getIntegerValue, getBigDecimalValue, getBooleanValue, getDoubleValue, ...) first calls ensureValueState(), which requires the parser to be at an object attribute value position (state OBJECT) or inside an array (state ARRAY). Calling any typed getter in another state throws this IllegalStateException with the actual state in the message.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/type/format/StringJsonDocumentReader.java:381

		if (endingQuote == -1) {
			throw new IllegalStateException("Can't find ending quote of key name");
		}

		this.jsonValueEnd = endingQuote;
		this.jsonValueStart = position;

		this.position =  endingQuote + 1;

	}

	/**
	 * Ensures that the current state is on value.
	 * @throws IllegalStateException if not on "value" state
	 */
	private void ensureValueState() throws IllegalStateException {
		if ( (this.processingStates.getCurrent() != JsonProcessingState.OBJECT ) &&
			this.processingStates.getCurrent() != JsonProcessingState.ARRAY)  {
			throw new IllegalStateException( "unexpected processing state: " + this.processingStates.getCurrent() );
		}
	}
	/**
	 * Ensures that we have a value ready to be exposed. i.e we just consume one.
	 * @throws IllegalStateException if no value available
	 */
	private void ensureAvailableValue() throws IllegalStateException {
		if (this.jsonValueEnd == 0 ) {
			throw new IllegalStateException( "No available value");
		}
	}

	@Override
	public String getObjectKeyName() {
		if ( this.processingStates.getCurrent() != JsonProcessingState.OBJECT_KEY_NAME ) {
			throw new IllegalStateException( "unexpected processing state: " + this.processingStates.getCurrent() );
		}
		ensureAvailableValue();

View on GitHub (pinned to fad1729dce)

Solutions

  1. Drive all accessor calls from the JsonDocumentItemType returned by next(): only call typed getters after VALUE, NUMERIC_VALUE, BOOLEAN_VALUE or NULL_VALUE items
  2. Call getObjectKeyName() only after VALUE_KEY, and match the getter to the item type (NUMERIC_VALUE → getIntegerValue/getLongValue/getBigDecimalValue, BOOLEAN_VALUE → getBooleanValue)
  3. Encapsulate the protocol once in a small traversal wrapper so call sites cannot get it wrong

Example fix

// before
JsonDocumentItemType item = reader.next(); // returned VALUE_KEY
String s = reader.getStringValue(); // IllegalStateException: state is OBJECT_KEY_NAME
// after
switch (reader.next()) {
    case VALUE_KEY:
        String key = reader.getObjectKeyName();
        break;
    case VALUE:
    case NUMERIC_VALUE:
    case BOOLEAN_VALUE:
    case NULL_VALUE:
        String s2 = reader.getStringValue();
        break;
}
Defensive patterns

Strategy: validation

Validate before calling

static boolean isAtValue(JsonDocumentItemType lastItem) {
    return lastItem == JsonDocumentItemType.VALUE
            || lastItem == JsonDocumentItemType.NUMERIC_VALUE
            || lastItem == JsonDocumentItemType.BOOLEAN_VALUE
            || lastItem == JsonDocumentItemType.NULL_VALUE;
}

// usage: track the item returned by next() and only call typed getters when isAtValue(lastItem) is true

Try / catch

try {
    value = reader.getStringValue();
} catch (IllegalStateException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("unexpected processing state")) {
        // protocol violation: a value item was not consumed before the getter
        skipToNextValue(reader);
        return null;
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling getStringValue()/getIntegerValue()/... immediately after next() returned VALUE_KEY (state OBJECT_KEY_NAME), before any object/array was entered (state NONE/STARTING_OBJECT), or at any point where the parser sits on a key rather than a value.

Common situations: Custom JSON/XML format mappers, aggregate mapping code, or traversal utilities that call a typed getter at the wrong step of the pull protocol; code ported from a push-style API where characters arrive in callbacks; copy-pasted loops assuming the first next() already yields a value.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/08ded05244932c8d. Report an issue: GitHub.