mybatis/mybatis-3 · error · IncompleteElementException
Cache-ref not yet resolved
Error message
Cache-ref not yet resolved
What it means
Thrown by addMappedStatement() when the flag unresolvedCacheRef is still true: this mapper's <cache-ref> could not be resolved yet, so statements must not be cached with a null/stale cache. It is an IncompleteElementException, so the whole mapped statement is deferred and rebuilt on a later parse pass once the referenced cache exists.
Source
Thrown at src/main/java/org/apache/ibatis/builder/MapperBuilderAssistant.java:208
ResultMapping resultMapping = buildResultMapping(resultType, null, column, javaType, jdbcType, null, null, null,
null, typeHandler, new ArrayList<>(), null, null, false);
Map<String, String> namespaceDiscriminatorMap = new HashMap<>();
for (Map.Entry<String, String> e : discriminatorMap.entrySet()) {
String resultMap = e.getValue();
resultMap = applyCurrentNamespace(resultMap, true);
namespaceDiscriminatorMap.put(e.getKey(), resultMap);
}
return new Discriminator.Builder(configuration, resultMapping, namespaceDiscriminatorMap).build();
}
public MappedStatement addMappedStatement(String id, SqlSource sqlSource, StatementType statementType,
SqlCommandType sqlCommandType, Integer fetchSize, Integer timeout, String parameterMap, Class<?> parameterType,
String resultMap, Class<?> resultType, ResultSetType resultSetType, boolean flushCache, boolean useCache,
boolean resultOrdered, KeyGenerator keyGenerator, String keyProperty, String keyColumn, String databaseId,
LanguageDriver lang, String resultSets, boolean dirtySelect, ParamNameResolver paramNameResolver) {
if (unresolvedCacheRef) {
throw new IncompleteElementException("Cache-ref not yet resolved");
}
id = applyCurrentNamespace(id, false);
MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, id, sqlSource, sqlCommandType)
.resource(resource).fetchSize(fetchSize).timeout(timeout).statementType(statementType)
.keyGenerator(keyGenerator).keyProperty(keyProperty).keyColumn(keyColumn).databaseId(databaseId).lang(lang)
.resultOrdered(resultOrdered).resultSets(resultSets)
.resultMaps(getStatementResultMaps(resultMap, resultType, id)).resultSetType(resultSetType)
.flushCacheRequired(flushCache).useCache(useCache).cache(currentCache).dirtySelect(dirtySelect)
.paramNameResolver(paramNameResolver);
ParameterMap statementParameterMap = getStatementParameterMap(parameterMap, parameterType, id);
if (statementParameterMap != null) {
statementBuilder.parameterMap(statementParameterMap);
}
MappedStatement statement = statementBuilder.build();View on GitHub (pinned to 008069adb1)
Solutions
- Fix the underlying cache-ref: make sure the referenced namespace exists and declares a cache (see errors 22/23)
- Check that the referenced mapper file is included in the configuration before relying on its cache
- As a workaround while isolating the problem, temporarily replace cache-ref with a local <cache/> declaration
Example fix
<!-- before: CommonMapper.xml has no cache --> <cache-ref namespace="com.acme.CommonMapper"/> <!-- after: declare a cache in CommonMapper.xml --> <cache/>
Defensive patterns
Strategy: validation
Validate before calling
// Verify all cache-ref namespaces resolved after factory build
Configuration cfg = factory.getConfiguration();
// incomplete refs are gone only when resolved; assert none linger:
if (!cfg.getIncompleteCacheRefs().isEmpty()) {
throw new IllegalStateException("Unresolved cache-refs: " + cfg.getIncompleteCacheRefs());
} Prevention
- Declare the shared cache in the least-dependent (base) mapper so refs always resolve
- Treat any 'Cache-ref not yet resolved' surfacing at runtime as a startup config bug — fix the cache-ref, do not catch it
When it happens
Trigger: A mapper with <cache-ref namespace="X"/> where X's cache is not yet registered when the mapper's <select>/<insert>/... elements are processed; the statement build aborts here and the incomplete statement is queued for retry.
Common situations: Normal cross-mapper cache-ref ordering at startup (usually resolves on retry), or a permanent failure combining a dangling cache-ref with statements — the final error surfaced to the user is typically this one at the end of configuration parsing.
Related errors
- No cache for namespace '{namespace}' could be found.
- Could not find result map '{resultMapName}' referenced from
- cache-ref element requires a namespace attribute.
- Could not find a parent resultMap with id '{extend}'
- Could not find parameter map {parameterMapName}
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/bc8ff8f12e553a3d.
Report an issue: GitHub.