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
- Drive all accessor calls from the JsonDocumentItemType returned by next(): only call typed getters after VALUE, NUMERIC_VALUE, BOOLEAN_VALUE or NULL_VALUE items
- Call getObjectKeyName() only after VALUE_KEY, and match the getter to the item type (NUMERIC_VALUE → getIntegerValue/getLongValue/getBigDecimalValue, BOOLEAN_VALUE → getBooleanValue)
- 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
- Model the pull protocol explicitly: one switch over JsonDocumentItemType drives every accessor call
- Typed getters only after VALUE/NUMERIC_VALUE/BOOLEAN_VALUE/NULL_VALUE; getObjectKeyName only after VALUE_KEY
- Write one shared traversal helper instead of scattering direct reader calls
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
- Unexpected JsonProcessingState {}
- unexpected quote read in current processing state {}
- unexpected read [{}] in current processing state {}
- No available value
- forEachRemaining
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/08ded05244932c8d.
Report an issue: GitHub.