{"record":{"id":"613e3fb443d016df","repo":"mybatis/mybatis-3","slug":"cannot-get-configuration-as-factory-method-th-613e3f","errorCode":null,"errorMessage":"Cannot get Configuration as factory method [\" + this.configurationFactory + \"]#[\" + FACTORY_METHOD + \"] threw an exception.\"","messagePattern":"Cannot get Configuration as factory method \\[\" \\+ this\\.configurationFactory \\+ \"\\]#\\[\" \\+ FACTORY_METHOD \\+ \"\\] threw an exception\\.\"","errorType":"exception","errorClass":"ExecutorException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/apache/ibatis/executor/loader/ResultLoaderMap.java","lineNumber":256,"sourceCode":"        if (!factoryMethod.canAccess(null)) {\n          configurationObject = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {\n            try {\n              factoryMethod.setAccessible(true);\n              return factoryMethod.invoke(null);\n            } finally {\n              factoryMethod.setAccessible(false);\n            }\n          });\n        } else {\n          configurationObject = factoryMethod.invoke(null);\n        }\n      } catch (final ExecutorException ex) {\n        throw ex;\n      } catch (final NoSuchMethodException ex) {\n        throw new ExecutorException(\"Cannot get Configuration as factory class [\" + this.configurationFactory\n            + \"] is missing factory method of name [\" + FACTORY_METHOD + \"].\", ex);\n      } catch (final PrivilegedActionException ex) {\n        throw new ExecutorException(\"Cannot get Configuration as factory method [\" + this.configurationFactory + \"]#[\"\n            + FACTORY_METHOD + \"] threw an exception.\", ex.getCause());\n      } catch (final Exception ex) {\n        throw new ExecutorException(\"Cannot get Configuration as factory method [\" + this.configurationFactory + \"]#[\"\n            + FACTORY_METHOD + \"] threw an exception.\", ex);\n      }\n\n      if (!(configurationObject instanceof Configuration)) {\n        throw new ExecutorException(\"Cannot get Configuration as factory method [\" + this.configurationFactory + \"]#[\"\n            + FACTORY_METHOD + \"] didn't return [\" + Configuration.class + \"] but [\"\n            + (configurationObject == null ? \"null\" : configurationObject.getClass()) + \"].\");\n      }\n\n      return Configuration.class.cast(configurationObject);\n    }\n\n    private Log getLogger() {\n      if (this.log == null) {\n        this.log = LogFactory.getLog(this.getClass());","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/mybatis/mybatis-3/blob/008069adb1b089579b5dcba87ee591908b263274/src/main/java/org/apache/ibatis/executor/loader/ResultLoaderMap.java#L238-L274","documentation":"Thrown when the factory method itself blows up while MyBatis rebuilds the Configuration for a deserialized lazy object. The privileged invocation path (factory method not publicly accessible, so it is invoked inside AccessController.doPrivileged) throws a PrivilegedActionException; MyBatis unwraps ex.getCause() and reports it as the reason getConfiguration() failed.","triggerScenarios":"LoadPair.getConfiguration() calls the static getConfiguration() of configurationFactory through setAccessible(true)/invoke inside a privileged block, and the method throws (NPE on an uninitialized singleton, class not found during the call, IllegalAccess on invoke).","commonSituations":"Factory method dereferences a static field that is still null at deserialization time (e.g. framework not yet initialized); factory delegating to a Spring context that is not ready; the exception cause shown is the user's own bug inside getConfiguration().","solutions":["Read the cause chain: the reported cause exception is thrown by your getConfiguration() body — fix that (usually an uninitialized singleton)","Make the factory lazily build/caching the SqlSessionFactory instead of depending on startup order","Initialize the factory before any deserialized lazy object is touched (e.g. ServletContextListener before session deserialization)"],"exampleFix":"// before\npublic static Configuration getConfiguration() {\n  return AppContext.getBean(SqlSessionFactory.class).getConfiguration(); // AppContext null early\n}\n// after\nprivate static volatile Configuration cached;\npublic static Configuration getConfiguration() {\n  if (cached == null) cached = buildFactory().getConfiguration();\n  return cached;\n}","handlingStrategy":"try-catch","validationCode":"// Call the factory during startup; any user-code exception surfaces immediately\nConfiguration cfg = MyConfigFactory.getConfiguration();\nassert cfg != null;","typeGuard":null,"tryCatchPattern":"try { lazy.getProp(); } catch (ExecutorException e) { Throwable cause = e.getCause(); // the factory's own exception log and fix cause; rethrow; }","preventionTips":["Initialize the Configuration before exposing the app to serialized objects","Make the factory lazy-caching and null-safe","Cluster nodes must complete bootstrap before deserializing sessions"],"tags":["mybatis","lazy-loading","reflection","initialization"],"backgroundTag":null,"analyzedSha":"008069adb1b089579b5dcba87ee591908b263274","analyzedAt":"2026-08-14T13:07:10.264Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}