mybatis/mybatis-3 · error · ExecutorException

Cannot get Configuration as configuration factory was not…

Error message

Cannot get Configuration as configuration factory was not set.

What it means

Thrown when MyBatis must rebuild the lazy-loading machinery of a deserialized object but the configurationFactory was never set. Because LoadPair is serialized without the live Configuration, the only way to get it back is a user-supplied factory class; if lazyLoadingEnabled is true but configurationFactory is omitted in the mybatis-config settings, this fails.

Solutions

  1. Add <setting name="configurationFactory" value="com.example.MyConfigFactory"/> to the <settings> block of mybatis-config.xml
  2. Ensure the factory class has a public static Configuration getConfiguration() method returning the live SqlSessionFactory's Configuration
  3. Pre-load lazy properties before serialization so no Configuration rebuild is needed
  4. Make the statement parameter object Serializable so the LoadPair actually records the factory at build time

Example fix

<!-- before -->
<settings>
  <setting name="lazyLoadingEnabled" value="true"/>
</settings>
<!-- after -->
<settings>
  <setting name="lazyLoadingEnabled" value="true"/>
  <setting name="configurationFactory" value="com.example.MyBatisConfigFactory"/>
</settings>
Defensive patterns

Strategy: validation

Validate before calling

// At startup, fail fast if lazy loading is on but the factory is unset
Configuration cfg = sqlSessionFactory.getConfiguration();
if (cfg.isLazyLoadingEnabled() && cfg.getConfigurationFactory() == null) {
  throw new IllegalStateException("Set configurationFactory when lazyLoadingEnabled=true");
}

Try / catch

try { lazyObj.getLazyProp(); } catch (ExecutorException e) { if (e.getMessage().contains("configuration factory was not set")) { log.error("Config error: add configurationFactory setting", e); } throw e; }

Prevention

When it happens

Trigger: A deserialized lazy-loading proxy has load(userObject) called (metaResultObject/resultLoader null), mappedParameter non-null, and LoadPair.getConfiguration() finds this.configurationFactory == null, i.e. <setting name='lazyLoadingEnabled' value='true'/> without <setting name='configurationFactory' value='...'/>.

Common situations: Enabling lazy loading for serializable result objects (session replication, distributed caches) but forgetting the configurationFactory setting; configurationFactory silently not serialized because the parameter object was not Serializable so the field was never populated.

Related errors


AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14). Data as JSON: /api/errors/ff68aa6aebcee81c. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/org/apache/ibatis/executor/loader/ResultLoaderMap.java:227

            metaResultObject.getSetterType(this.property), null, null);
      }

      /*
       * We are using a new executor because we may be (and likely are) on a new thread and executors aren't thread
       * safe. (Is this sufficient?) A better approach would be making executors thread safe.
       */
      if (this.serializationCheck == null) {
        final ResultLoader old = this.resultLoader;
        this.resultLoader = new ResultLoader(old.configuration, new ClosedExecutor(), old.mappedStatement,
            old.parameterObject, old.targetType, old.cacheKey, old.boundSql);
      }

      this.metaResultObject.setValue(property, this.resultLoader.loadResult());
    }

    private Configuration getConfiguration() {
      if (this.configurationFactory == null) {
        throw new ExecutorException("Cannot get Configuration as configuration factory was not set.");
      }

      Object configurationObject;
      try {
        final Method factoryMethod = this.configurationFactory.getDeclaredMethod(FACTORY_METHOD);
        if (!Modifier.isStatic(factoryMethod.getModifiers())) {
          throw new ExecutorException("Cannot get Configuration as factory method [" + this.configurationFactory + "]#["
              + FACTORY_METHOD + "] is not static.");
        }

        if (!factoryMethod.canAccess(null)) {
          configurationObject = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
            try {
              factoryMethod.setAccessible(true);
              return factoryMethod.invoke(null);
            } finally {
              factoryMethod.setAccessible(false);
            }

View on GitHub (pinned to 008069adb1)