"Unable to set company ID on locked company thread local" - 500 server error

Hi everyone,

My server is constantly being scanned by malicious bots. I proxy requests via nginx and use crowdsec waf but the volume is still enough to cause issue on Liferay (docker 2026-q2). It appears that tomcat threat takes out a lock on threadlocal and then don’t release it before returning the thread to the pool when there is a 404(?) and then subsequent requests using that thread fail. Is this a bug or is there a config issue I need to fix? It makes the site unusable for most requests.

30-Aug-2026 04:45:37.661 SEVERE [http-nio-8080-exec-6] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [default] in context with path [] threw exception
    java.lang.UnsupportedOperationException: Unable to set company ID on locked company thread local
        at com.liferay.portal.util.PortalInstances.getCompanyId(PortalInstances.java:177)
        at com.liferay.portal.servlet.filters.portal.instances.PortalInstancesFilter.doFilterTry(PortalInstancesFilter.java:43)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDirectCallFilter(InvokerFilterChain.java:187)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:92)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilter.doFilter(InvokerFilter.java:114)
        at com.liferay.shielded.container.internal.proxy.FilterWrapper.doFilter(FilterWrapper.java:69)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:162)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:138)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:165)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:88)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:492)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:113)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:83)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:72)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:1272)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1797)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
        at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:973)
        at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:491)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
        at java.base/java.lang.Thread.run(Thread.java:1583)

2 Answers

2

Hey @Mark_Clarke ,

I’ve run into this same issue. It is fixed in 2026.Q2.5+ (LPD-94712), so I am not sure what version you are running.

At a high level, when a bot request triggers an exception downstream of PortalInstancesFilter, the filter sets the company ID on CompanyThreadLocal but does not restore it before the thread is returned to Tomcat’s thread pool.

This effectively “poisons” the worker thread. When that same thread is reused for another request, it fails with:

java.lang.UnsupportedOperationException: Unable to set company ID on locked company thread local

With a high volume of bot/scanner traffic, threads can become poisoned faster than they are naturally rotated, which can eventually make the entire site appear unusable. I think this is what you are also experiencing.

If upgrading is not possible at the moment you could consider hardening nginx to drop common scanner paths before they even reach Tomcat as a more immediate workaround.

Hope this helps!

Thanks for the information. I have increased our block list size for now.