Catalog - Null Pointer Exception - when removing DISCOUNT phase from plan.

19 views
Skip to first unread message

Vivek Manpuria (Vivek)

unread,
Jul 14, 2025, 4:42:40 PMJul 14
to Kill Bill users mailing-list
Dear Team,

Updating a plan, in the catalog caused a null pointer exception. I have noticed such exceptions for the following kind of operations:
  1. removing a trial phase
  2. changing a TRIAL phase to a DISCOUNT phase
  3. changing a TRiAL phase from a fixed price to recurring price.
Are the above operations not permitted in the catalog?

When I delete the catalog and then upload the catalog afresh, it is accepted. Only, changing an existing catalog leads to a NullPointerException.

Below, please find logs for a null pointer exception, when I removed a DISCOUNT phase in a plan that had 3 trial phases, 1 discount phase and 1 evergreen phase.

I do not have logs for the other failed scenarios.

Thank you,
Vivek

---- logs -----

---- exception -----

{ "@timestamp": "2025-07-14T20:27:00.056Z", "message": "Unexpected NullPointerException", "logger_name": "org.killbill.billing.jaxrs.mappers.RuntimeExceptionMapper", "thread_name": "catalina-exec-4", "level": "WARN", "req.requestURI": "/1.0/kb/catalog/xml/validate", "kb.tenantRecordId": "1", "kb.userToken": "9c005847-06c0-4fce-9292-388b683edf2d", "req.requestId": "9c005847-06c0-4fce-9292-388b683edf2d", "req.method": "POST", "req.remoteHost": "198.178.10.52", "req.requestURL": "https://lms.dev.commerce.comcast.com/1.0/kb/catalog/xml/validate", "req.userAgent": "insomnia/10.3.1", "stack_trace": "java.lang.NullPointerException: null\n\tat org.killbill.billing.catalog.DefaultVersionedCatalog.validatePlanShape(DefaultVersionedCatalog.java:188)\n\tat org.killbill.billing.catalog.DefaultVersionedCatalog.validateUniformPlanShapeAcrossVersions(DefaultVersionedCatalog.java:165)\n\tat org.killbill.billing.catalog.DefaultVersionedCatalog.validate(DefaultVersionedCatalog.java:151)\n\tat org.killbill.billing.catalog.api.user.DefaultCatalogUserApi.validateCatalogInternal(DefaultCatalogUserApi.java:235)\n\tat org.killbill.billing.catalog.api.user.DefaultCatalogUserApi.validateCatalog(DefaultCatalogUserApi.java:132)\n\tat org.killbill.billing.util.glue.KillbillApiAopModule$ProfilingMethodInterceptor$1.execute(KillbillApiAopModule.java:89)\n\tat org.killbill.commons.profiling.Profiling.executeWithProfiling(Profiling.java:35)\n\tat org.killbill.billing.util.glue.KillbillApiAopModule$ProfilingMethodInterceptor.invoke(KillbillApiAopModule.java:105)\n\tat org.killbill.billing.jaxrs.resources.CatalogResource.validateCatalogXml(CatalogResource.java:250)\n\tat org.killbill.billing.jaxrs.resources.CatalogResource_$$_jvstab6_0._d55validateCatalogXml(CatalogResource_$$_jvstab6_0.java)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n\tat java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n\tat java.base/java.lang.reflect.Method.invoke(Method.java:566)\n\tat org.glassfish.hk2.utilities.reflection.ReflectionHelper.invoke(ReflectionHelper.java:1268)\n\tat org.jvnet.hk2.internal.MethodInterceptorHandler$MethodInvocationImpl.proceed(MethodInterceptorHandler.java:164)\n\tat org.killbill.commons.skeleton.metrics.TimedResourceInterceptor.invoke(TimedResourceInterceptor.java:70)\n\tat org.jvnet.hk2.internal.MethodInterceptorHandler.invoke(MethodInterceptorHandler.java:97)\n\tat org.killbill.billing.jaxrs.resources.CatalogResource_$$_jvstab6_0.validateCatalogXml(CatalogResource_$$_jvstab6_0.java)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n\tat java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n\tat java.base/java.lang.reflect.Method.invoke(Method.java:566)\n\tat org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory.lambda$static$0(ResourceMethodInvocationHandlerFactory.java:52)\n\tat org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:134)\n\tat org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:177)\n\tat org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:176)\n\tat org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:81)\n\tat org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:478)\n\tat org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:400)\n\tat org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:81)\n\tat org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:256)\n\tat org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)\n\tat org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)\n\tat org.glassfish.jersey.internal.Errors.process(Errors.java:292)\n\tat org.glassfish.jersey.internal.Errors.process(Errors.java:274)\n\tat org.glassfish.jersey.internal.Errors.process(Errors.java:244)\n\tat org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:265)\n\tat org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:235)\n\tat org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:684)\n\tat org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:394)\n\tat org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:346)\n\tat org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:358)\n\tat org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:311)\n\tat org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:205)\n\tat com.google.inject.servlet.ServletDefinition.doServiceImpl(ServletDefinition.java:290)\n\tat com.google.inject.servlet.ServletDefinition.doService(ServletDefinition.java:280)\n\tat com.google.inject.servlet.ServletDefinition.service(ServletDefinition.java:184)\n\tat com.google.inject.servlet.ManagedServletPipeline.service(ManagedServletPipeline.java:89)\n\tat com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:85)\n\tat org.killbill.billing.server.security.TenantFilter.doFilter(TenantFilter.java:109)\n\tat com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)\n\tat org.killbill.billing.server.filters.ResponseCorsFilter.doFilter(ResponseCorsFilter.java:76)\n\tat com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)\n\tat ch.qos.logback.classic.helpers.MDCInsertingServletFilter.doFilter(MDCInsertingServletFilter.java:50)\n\tat com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)\n\tat com.google.inject.servlet.ManagedFilterPipeline.dispatch(ManagedFilterPipeline.java:121)\n\tat com.google.inject.servlet.GuiceFilter.doFilter(GuiceFilter.java:133)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)\n\tat org.apache.shiro.guice.web.SimpleFilterChain.doFilter(SimpleFilterChain.java:44)\n\tat org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)\n\tat org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)\n\tat org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:154)\n\tat org.apache.shiro.guice.web.SimpleFilterChain.doFilter(SimpleFilterChain.java:41)\n\tat org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)\n\tat org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)\n\tat org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:154)\n\tat org.apache.shiro.guice.web.SimpleFilterChain.doFilter(SimpleFilterChain.java:41)\n\tat org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:458)\n\tat org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:373)\n\tat org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)\n\tat org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)\n\tat org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:387)\n\tat org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:370)\n\tat org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:154)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)\n\tat org.killbill.commons.metrics.servlets.InstrumentedFilter.doFilter(InstrumentedFilter.java:139)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)\n\tat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:168)\n\tat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)\n\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482)\n\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130)\n\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)\n\tat org.apache.catalina.valves.rewrite.RewriteValve.invoke(RewriteValve.java:281)\n\tat org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:660)\n\tat org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:761)\n\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)\n\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:346)\n\tat org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:396)\n\tat org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)\n\tat org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:937)\n\tat org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1791)\n\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190)\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)\n\tat java.base/java.lang.Thread.run(Thread.java:829)\n" }



Reshma Bidikar

unread,
Jul 16, 2025, 1:50:44 AMJul 16
to Kill Bill users mailing-list
Hello Vivek,

Could you please share your catalog XML files and the exact steps that you follow that lead to the issue?

Also, just so you know, there are some known issues with plans having more than two phases. See  #1243.

Regards,
Reshma

Vivek Manpuria (Vivek)

unread,
Jul 26, 2025, 4:37:34 AMJul 26
to Kill Bill users mailing-list
Hi Reshma

Attached, please find the current catalog XML and the new catalog XML for which validation failed with the following response:
400 Bad Request
{
"className": "java.lang.NullPointerException",
"code": null,
"message": null,
"causeClassName": null,
"causeMessage": null,
"stackTrace": []
}

Steps that led to the issue:
1. plan, "_16106c36-5635-4e10-b30f-d60bc6c52188.discount" in current catalog has a TRIAL phase, a DISCOUNT phase and an EVERGREEN phase. (catalog-new.xml)
2. for the above plan, I changed the DISCOUNT phase to a TRIAL phase (catalog-new.XML)
3. NullPointerException response is received when catalog-new.XML is validated.

Thank you,
Vivek

catalog-current.xml
catalog-new.xml
Reply all
Reply to author
Forward
0 new messages