alibaba/spring-ai-alibaba · error · IllegalStateException

Metadata must be an object

Error message

Metadata must be an object

What it means

deserializeMetadata expects the 'metadata' JSON field of a serialized state/graph to be a JSON object that maps to Map<String,Object>. If the field exists but is a scalar, array, or other non-object node, the deserializer aborts with IllegalStateException because metadata cannot be represented otherwise.

Solutions

  1. Open the serialized file and make the 'metadata' field a JSON object ({...}) or remove it entirely (null/missing yields an empty map)
  2. Re-export the state with the same library version that wrote it originally
  3. If migrating formats, transform old metadata representation into a key/value object before loading
  4. Validate checkpoint JSON with a schema check (metadata: object|null) before loading

Example fix

// before
"metadata": "user-uploads"
// after
"metadata": {"owner": "user-uploads"}
Defensive patterns

Strategy: validation

Validate before calling

JsonNode meta = root.get("metadata");
if (meta != null && !meta.isNull() && !meta.isObject()) throw new IllegalArgumentException("metadata must be a JSON object");

Type guard

boolean isObjectNode(JsonNode n) { return n == null || n.isNull() || n.isObject(); }

Try / catch

try { loaded = loader.load(file); } catch (IllegalStateException e) { if ("Metadata must be an object".equals(e.getMessage())) { /* repair or regenerate the checkpoint */ } else throw e; }

Prevention

When it happens

Trigger: Loading a checkpoint/serialized state whose 'metadata' field is present but is a JSON scalar, string, or array instead of an object — typically from hand-editing, cross-version formats, or corrupt files.

Common situations: Manually written checkpoint JSON; metadata written by another tool/version with a different shape; truncated or concatenated JSON files.

Related errors


AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09). Data as JSON: /api/errors/b55afa518f130161. Report an issue: GitHub.

Appendix: source

Thrown at spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/serializer/plain_text/jackson/SerializationHelper.java:74

import com.fasterxml.jackson.databind.util.TokenBuffer;

class SerializationHelper {

	static final String METADATA_FIELD = "metadata";

	static Map<String, Object> deserializeMetadata(ObjectMapper mapper, JsonNode parentNode)
			throws JsonProcessingException {
		if (parentNode == null) {
			return Map.of();
		}

		var node = parentNode.findValue(METADATA_FIELD);

		if (node == null || node.isNull() || node.isEmpty()) {
			return Map.of();
		}
		if (!node.isObject()) {
			throw new IllegalStateException("Metadata must be an object");
		}
		return mapper.treeToValue(node, new TypeReference<>() {
		});
	}

	static void serializeMetadata(JsonGenerator gen, SerializerProvider provider, Map<String, Object> metadata)
			throws IOException {
		gen.writeObjectField(METADATA_FIELD, normalizeMetadataValue(provider, metadata));
	}

	private static Object normalizeMetadataValue(SerializerProvider provider, Object value) throws IOException {
		return normalizeMetadataValue(provider, value, JsonInclude.Include.ALWAYS);
	}

	private static Object normalizeMetadataValue(SerializerProvider provider, Object value,
			JsonInclude.Include contentInclusion) throws IOException {
		if (value instanceof Map<?, ?> map) {
			boolean preserveContainer = hasClassSerializationOverrides(provider, map.getClass());

View on GitHub (pinned to f82da0b50f)