{"record":{"id":"ed49a275262bfbdd","repo":"apolloconfig/apollo","slug":"spring-session-json-deserializing-error-this-is-u","errorCode":null,"errorMessage":"Spring-session JSON deserializing error, This is usually caused by the system upgrade, please clear the browser cookies and try again.","messagePattern":"Spring-session JSON deserializing error, This is usually caused by the system upgrade, please clear the browser cookies and try again\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":500,"severity":"error","filePath":"apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/config/SpringSessionConfig.java","lineNumber":61,"sourceCode":"  @ConditionalOnProperty(prefix = \"spring.session\", name = \"store-type\", havingValue = \"jdbc\")\n  public ConversionService springSessionConversionService() {\n    GenericConversionService conversionService = new GenericConversionService();\n    ObjectMapper objectMapper = this.objectMapper();\n    conversionService.addConverter(Object.class, byte[].class, source -> {\n      try {\n        return objectMapper.writeValueAsBytes(source);\n      } catch (IOException e) {\n        throw new RuntimeException(\n            \"Spring-session JSON serializing error, This is usually caused by the system upgrade, please clear the browser cookies and try again.\",\n            e);\n      }\n    });\n\n    conversionService.addConverter(byte[].class, Object.class, source -> {\n      try {\n        return objectMapper.readValue(source, Object.class);\n      } catch (IOException e) {\n        throw new RuntimeException(\n            \"Spring-session JSON deserializing error, This is usually caused by the system upgrade, please clear the browser cookies and try again.\",\n            e);\n      }\n    });\n    return conversionService;\n  }\n\n  @Bean(\"springSessionDefaultRedisSerializer\")\n  @ConditionalOnProperty(prefix = \"spring.session\", name = \"store-type\", havingValue = \"redis\")\n  public RedisSerializer<Object> springSessionDefaultRedisSerializer() {\n    return new GenericJackson2JsonRedisSerializer(objectMapper());\n  }\n\n  /**\n   * Customized {@link ObjectMapper} to add mix-in for class that doesn't have default constructors\n   *\n   * @return the {@link ObjectMapper} to use\n   */","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/apolloconfig/apollo/blob/d95fc18d112589efc09ddcbe1507047584d55251/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/config/SpringSessionConfig.java#L43-L79","documentation":"Thrown by the JDBC Spring-session converter in the reverse direction (byte[] -> Object) when objectMapper.readValue(source, Object.class) fails. The stored bytes no longer deserialize into a Java object, so the session cannot be restored and the request is rejected (HTTP 500). Like its serialize counterpart, the message attributes the cause to a system upgrade that changed the serialized class shape.","triggerScenarios":"A returning portal user whose session row was written by an older portal version (or a different ObjectMapper config) issues a request that needs to read the session, while spring.session.store-type=jdbc and the stored JSON no longer matches the current class structure.","commonSituations":"Portal upgraded across versions; session DB restored from a backup taken under another build; class refactored/renamed/moved package without a @JsonTypeInfo polymorphic mapping or default typing.","solutions":["Clear the affected browser cookies and the matching SPRING_SESSION rows, then authenticate fresh so a new session is written.","Check portal logs for the wrapped IOException / InvalidFormatException to learn which attribute and field fail to deserialize.","If you intentionally changed session attribute classes, flush all sessions in the DB after deploy.","Keep the ObjectMapper returned by SpringSessionConfig.objectMapper() stable across releases (same default typing, same mix-ins)."],"exampleFix":"// before: stored session has a class that no longer exists -> readValue throws\n// (no code change fixes a corrupted row; you must drop it)\n\n// after: on upgrade, purge stale sessions, then users re-login\nDELETE FROM SPRING_SESSION WHERE CREATION_TIME < <upgrade_time>;","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// A stale/corrupted session row usually recovers once the session is recreated.\ntry {\n  return portal.withSession(storedSession).call();\n} catch (HttpServerErrorException e) {\n  if (e.getResponseBodyAsString().contains(\"Spring-session JSON deserializing error\")) {\n    clearPortalCookies();          // discard JSESSIONID\n    return portal.freshLogin().call();   // retry once with a clean session\n  }\n  throw e;\n}","preventionTips":["Treat a deserialization 500 as a signal to recreate the session, not as a hard failure.","Purge SPRING_SESSION rows when changing session attribute class shapes.","Pin portal and session schema versions together in deploy runbooks.","Avoid long-lived sessions across upgrades."],"tags":["spring-session","deserialization","jdbc","jackson","session","upgrade"],"backgroundTag":null,"analyzedSha":"d95fc18d112589efc09ddcbe1507047584d55251","analyzedAt":"2026-08-14T04:00:05.477Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}