alibaba/arthas · error · NullPointerException

model class is null

Error message

model class is null

What it means

GrpcResultViewResolver.registerView(GrpcResultView view) throws NullPointerException when getModelClass(view) returns null — i.e. the view's model class could not be determined via reflection of its draw method signature. The resolver keys views by their associated ResultModel subclass; without it registration is impossible.

Source

Thrown at labs/arthas-grpc-web-proxy/src/main/java/com/taobao/arthas/grpcweb/grpc/view/GrpcResultViewResolver.java:102

        } catch (Throwable e) {
            logger.error("register result view failed", e);
        }
    }

    public GrpcResultView getResultView(ResultModel model) {
        return resultViewMap.get(model.getClass());
    }

    public GrpcResultViewResolver registerView(Class modelClass, GrpcResultView view) {
        //TODO 检查model的type是否重复,避免复制代码带来的bug
        this.resultViewMap.put(modelClass, view);
        return this;
    }

    public GrpcResultViewResolver registerView(GrpcResultView view) {
        Class modelClass = getModelClass(view);
        if (modelClass == null) {
            throw new NullPointerException("model class is null");
        }
        return this.registerView(modelClass, view);
    }

    public void registerView(Class<? extends GrpcResultView> viewClass) {
        GrpcResultView view = null;
        try {
            view = viewClass.newInstance();
        } catch (Throwable e) {
            throw new RuntimeException("create view instance failure, viewClass:" + viewClass, e);
        }
        this.registerView(view);
    }

    /**
     * Get model class of result view
     *
     * @return

View on GitHub (pinned to 21cf2e9ba5)

Solutions

  1. Ensure the view's draw method declares a concrete ResultModel subclass as its model parameter (not Object or a raw type).
  2. Use the two-argument overload registerView(modelClass, view) to specify the class explicitly when reflection cannot infer it.
  3. If using a lambda/anonymous view, replace it with a named class that retains generic type info.

Example fix

// before: model type erased, getModelClass returns null
resolver.registerView(myLambdaView); // throws 'model class is null'

// after: specify explicitly
resolver.registerView(MyResultModel.class, myLambdaView);
Defensive patterns

Strategy: validation

Validate before calling

Class modelClass = GrpcResultViewResolver.getModelClass(view);
if (modelClass == null) {
    // use explicit overload to avoid the NPE
    resolver.registerView(knownModelClass, view);
} else {
    resolver.registerView(view);
}

Try / catch

try {
    resolver.registerView(view);
} catch (NullPointerException e) {
    if (e.getMessage().contains("model class is null")) {
        resolver.registerView(MyResultModel.class, view); // explicit
    } else { throw e; }
}

Prevention

When it happens

Trigger: Registering a GrpcResultView whose draw method's second parameter is not a concrete ResultModel subclass, or whose generic type information is erased/unavailable at runtime, so reflection cannot extract the model class.

Common situations: A custom view class uses a raw type or Object as the model parameter instead of a concrete ResultModel subclass; the view is a lambda or anonymous class with erased generics; the draw method signature doesn't match the expected pattern getModelClass() inspects.

Related errors


AI-assisted analysis of alibaba/arthas@21cf2e9ba5 (2026-08-14). Data as JSON: /api/errors/835b99c78515822f. Report an issue: GitHub.