baomidou/mybatis-plus · error · BindingException

Mapper method '%s' attempted to return null from a method wi

Error message

Mapper method '%s' attempted to return null from a method with a primitive return type (%s).

What it means

The executed statement returned null but the mapper method's return type is a primitive (int, long, boolean...). Java cannot represent null for primitives, so the mapper method invocation fails rather than silently returning 0/false. The message names the offending method and its primitive type.

Source

Thrown at mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/override/MybatisMapperMethod.java:124

                        result = executeForIPage(sqlSession, args);
                    } else {
                        Object param = this.convertArgsToSqlCommandParam(args);
                        result = sqlSession.selectOne(command.getName(), param);
                        if (method.returnsOptional()
                            && (result == null || !method.getReturnType().equals(result.getClass()))) {
                            result = Optional.ofNullable(result);
                        }
                    }
                }
                break;
            case FLUSH:
                result = sqlSession.flushStatements();
                break;
            default:
                throw new BindingException("Unknown execution method for: " + command.getName());
        }
        if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
            throw new BindingException("Mapper method '" + command.getName()
                + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
        }
        return result;
    }

    @SuppressWarnings("all")
    private <E> Object executeForIPage(SqlSession sqlSession, Object[] args) {
        IPage<E> result = null;
        for (Object arg : args) {
            if (arg instanceof IPage) {
                result = (IPage<E>) arg;
                break;
            }
        }
        Assert.notNull(result, "can't found IPage for args!");
        Object param = this.convertArgsToSqlCommandParam(args);
        List<E> list = sqlSession.selectList(command.getName(), param);
        result.setRecords(list);

View on GitHub (pinned to bf67d90747)

Solutions

  1. Change the mapper method return type to the wrapper class (Integer/Long/Boolean) and null-check at the call site
  2. If an interceptor is returning null, fix it to return an empty/appropriate result
  3. Verify the statement really returns a value for the given call shape

Example fix

// before
int countAdults(@Param("age") int age);
// after
Integer countAdults(@Param("age") int age);
// call site
int n = Optional.ofNullable(mapper.countAdults(18)).orElse(0);
Defensive patterns

Strategy: type-guard

Type guard

// Enforce non-primitive returns on mapper write methods with a ArchUnit-style rule:
// methods declared on *Mapper interfaces that bind to INSERT/UPDATE/DELETE must return
// void | Integer | int | Long | long | Boolean | boolean
static boolean legalWriteReturn(Class<?> rt) {
    return rt == void.class || rt == Void.class || rt == Integer.class || rt == int.class
        || rt == Long.class || rt == long.class || rt == Boolean.class || rt == boolean.class;
}

Try / catch

catch BindingException at the call site only to log which method/return type collided; the real fix is the signature — no retry helps.

Prevention

When it happens

Trigger: A mapper method declared 'int count(...)' or 'boolean exists(...)' whose SQL/procedure path yields no result object (e.g. a stored procedure returning void in a SELECT-shaped call, or an interceptor returning null from query interception).

Common situations: Interceptors (e.g. tenant/data-permission plugins) short-circuiting and returning null; calling a PROCEDURE as if it returned a value; method signatures written with primitives for stylistic brevity.

Related errors


AI-assisted analysis of baomidou/mybatis-plus@bf67d90747 (2026-08-14). Data as JSON: /api/errors/947d216e044314bb. Report an issue: GitHub.