Julien Ledoux created NIFI-14369:
------------------------------------

             Summary: GitHubFlowRegistryClient reaches GitHub API quotas limits
                 Key: NIFI-14369
                 URL: https://issues.apache.org/jira/browse/NIFI-14369
             Project: Apache NiFi
          Issue Type: Bug
    Affects Versions: 2.3.0, 2.2.0, 2.1.0, 2.0.0
         Environment: Official Docker Images 2.0.0 stable running on Ubuntu 
22.04.4 LTS and Docker v27.0.3
            Reporter: Julien Ledoux


When using GitHubFlowRegistryClient with a GitHub App installation token and 
more than 10 versioned workflows, you may frequently encounter an issue where 
GitHub stops responding for no apparent reason. In such cases, the NiFi 
Registry dialog simply displays a red error message like "[object Object]".

To diagnose the issue, you'll need to check the nifi-user.log file. However, 
since its content is not sent to the Docker container's stdout, you'll need to 
mount the logs folder in a volume to access it locally, or login into the 
docker container.

Upon inspecting the logs, you’ll likely find the following error message:
{code:java}
2025-02-27 10:27:57,187 WARN [NiFi Web Server-271] 
o.a.n.w.a.config.NiFiCoreExceptionMapper org.apache.nifi.web.NiFiCoreException: 
Unable to get branches for registry with ID 
bcb1f2db-0194-1000-e6ec-53e8c29cfce8: {"message":"API rate limit exceeded for 
installation ID xxxxxxxx. If you reach out to GitHub Support for help, please 
include the request ID 27EC:10FD3E:2CFBDC2:2EAF364:67C02FDE and timestamp 
2025-02-27 09:26:57 
UTC.","documentation_url":"https://docs.github.com/rest/overview/rate-limits-for-the-rest-api","status":"403"}.
 Returning Conflict response.
org.apache.nifi.web.NiFiCoreException: Unable to get branches for registry with 
ID bcb1f2db-0194-1000-e6ec-53e8c29cfce8: {"message":"API rate limit exceeded 
for installation ID xxxxxxxx. If you reach out to GitHub Support for help, 
please include the request ID 27EC:10FD3E:2CFBDC2:2EAF364:67C02FDE and 
timestamp 2025-02-27 09:26:57 
UTC.","documentation_url":"https://docs.github.com/rest/overview/rate-limits-for-the-rest-api","status":"403"}
    at 
org.apache.nifi.web.dao.impl.StandardFlowRegistryDAO.getBranchesForUser(StandardFlowRegistryDAO.java:133)
    at 
org.apache.nifi.web.StandardNiFiServiceFacade.getBranches(StandardNiFiServiceFacade.java:3285)
    at 
java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
    at java.base/java.lang.reflect.Method.invoke(Method.java:580)
    at 
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:355)
    at 
org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
    at 
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at 
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768)
    at 
org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89)
    at 
org.apache.nifi.web.NiFiServiceFacadeLock.proceedWithReadLock(NiFiServiceFacadeLock.java:161)
    at 
org.apache.nifi.web.NiFiServiceFacadeLock.getLock(NiFiServiceFacadeLock.java:120)
    at 
java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
    at java.base/java.lang.reflect.Method.invoke(Method.java:580)
    at 
org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:637)
    at 
org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:627)
    at 
org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:71)
    at 
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at 
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768)
    at 
org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
    at 
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at 
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768)
    at 
org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:720)
    at 
org.apache.nifi.web.StandardNiFiServiceFacade$$SpringCGLIB$$0.getBranches(<generated>)
    at org.apache.nifi.web.api.FlowResource.getBranches(FlowResource.java:2344)
    at 
java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
    at java.base/java.lang.reflect.Method.invoke(Method.java:580)
    at 
org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory.lambda$static$0(ResourceMethodInvocationHandlerFactory.java:52)
    at 
org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:146)
    at 
org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:189)
    at 
org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:176)
    at 
org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:93)
    at 
org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:478)
    at 
org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:400)
    at 
org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:81)
    at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:274)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:292)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:274)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:244)
    at 
org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:266)
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:253)
    at 
org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:696)
    at 
org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:397)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:349)
    at 
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:358)
    at 
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:312)
    at 
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:205)
    at 
org.eclipse.jetty.ee10.servlet.ServletHolder$NotAsync.service(ServletHolder.java:1379)
    at 
org.eclipse.jetty.ee10.servlet.ServletHolder.handle(ServletHolder.java:736)
    at 
org.eclipse.jetty.ee10.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1614)
    at 
org.springframework.security.web.FilterChainProxy.lambda$doFilterInternal$3(FilterChainProxy.java:231)
    at 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:365)
    at 
org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:100)
    at 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at 
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:126)
    at 
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:120)
    at 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at 
org.apache.nifi.web.security.log.AuthenticationUserFilter.doFilterInternal(AuthenticationUserFilter.java:57)
    at 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at 
org.apache.nifi.web.security.NiFiAuthenticationFilter.authenticate(NiFiAuthenticationFilter.java:94)
    at 
org.apache.nifi.web.security.NiFiAuthenticationFilter.doFilter(NiFiAuthenticationFilter.java:56)
    at 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at 
org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100)
    at 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at 
org.springframework.security.oauth2.server.resource.web.authentication.BearerTokenAuthenticationFilter.doFilterInternal(BearerTokenAuthenticationFilter.java:128)
    at 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at 
org.apache.nifi.web.security.NiFiAuthenticationFilter.authenticate(NiFiAuthenticationFilter.java:94)
    at 
org.apache.nifi.web.security.NiFiAuthenticationFilter.doFilter(NiFiAuthenticationFilter.java:56)
    at 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at 
org.apache.nifi.web.security.csrf.CsrfCookieFilter.doFilterInternal(CsrfCookieFilter.java:43)
    at 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at 
org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:117)
    at 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at 
org.apache.nifi.web.security.csrf.SkipReplicatedCsrfFilter.doFilterInternal(SkipReplicatedCsrfFilter.java:59)
    at 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at 
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:62)
    at 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at 
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:233)
    at 
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:191)
    at 
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:362)
    at 
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:278)
    at 
org.eclipse.jetty.ee10.servlet.FilterHolder.doFilter(FilterHolder.java:205)
    at 
org.eclipse.jetty.ee10.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1586)
    at 
org.apache.nifi.web.filter.ExceptionFilter.doFilter(ExceptionFilter.java:44)
    at 
org.eclipse.jetty.ee10.servlet.FilterHolder.doFilter(FilterHolder.java:208)
    at 
org.eclipse.jetty.ee10.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1586)
    at 
org.eclipse.jetty.ee10.servlets.DoSFilter.doFilterChain(DoSFilter.java:462)
    at 
org.apache.nifi.web.server.filter.DataTransferExcludedDoSFilter.doFilterChain(DataTransferExcludedDoSFilter.java:51)
    at org.eclipse.jetty.ee10.servlets.DoSFilter.doFilter(DoSFilter.java:317)
    at org.eclipse.jetty.ee10.servlets.DoSFilter.doFilter(DoSFilter.java:282)
    at 
org.eclipse.jetty.ee10.servlet.FilterHolder.doFilter(FilterHolder.java:205)
    at 
org.eclipse.jetty.ee10.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1586)
    at 
org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
    at 
org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
    at 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at 
org.eclipse.jetty.ee10.servlet.FilterHolder.doFilter(FilterHolder.java:205)
    at 
org.eclipse.jetty.ee10.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1586)
    at 
org.eclipse.jetty.ee10.servlet.ServletHandler$MappedServlet.handle(ServletHandler.java:1547)
    at 
org.eclipse.jetty.ee10.servlet.ServletChannel.dispatch(ServletChannel.java:824)
    at 
org.eclipse.jetty.ee10.servlet.ServletChannel.handle(ServletChannel.java:436)
    at 
org.eclipse.jetty.ee10.servlet.ServletHandler.handle(ServletHandler.java:464)
    at 
org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:575)
    at 
org.eclipse.jetty.ee10.servlet.SessionHandler.handle(SessionHandler.java:717)
    at 
org.eclipse.jetty.server.handler.ContextHandler.handle(ContextHandler.java:1060)
    at 
org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:181)
    at 
org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:151)
    at org.eclipse.jetty.server.Server.handle(Server.java:182)
    at 
org.eclipse.jetty.server.internal.HttpChannelState$HandlerInvoker.run(HttpChannelState.java:662)
    at 
org.eclipse.jetty.server.internal.HttpConnection.onFillable(HttpConnection.java:414)
    at 
org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:322)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:99)
    at 
org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)
    at 
org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.runTask(AdaptiveExecutionStrategy.java:478)
    at 
org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.consumeTask(AdaptiveExecutionStrategy.java:441)
    at 
org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.tryProduce(AdaptiveExecutionStrategy.java:293)
    at 
org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.run(AdaptiveExecutionStrategy.java:201)
    at 
org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:311)
    at 
org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:979)
    at 
org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1209)
    at 
org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1164)
    at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: org.kohsuke.github.HttpException: {"message":"API rate limit 
exceeded for installation ID xxxxxxxx. If you reach out to GitHub Support for 
help, please include the request ID 27EC:10FD3E:2CFBDC2:2EAF364:67C02FDE and 
timestamp 2025-02-27 09:26:57 
UTC.","documentation_url":"https://docs.github.com/rest/overview/rate-limits-for-the-rest-api","status":"403"}
    at org.kohsuke.github.GitHubClient.interpretApiError(GitHubClient.java:740)
    at org.kohsuke.github.GitHubClient.sendRequest(GitHubClient.java:480)
    at org.kohsuke.github.GitHubPageIterator.fetch(GitHubPageIterator.java:146)
    at org.kohsuke.github.GitHubPageIterator.hasNext(GitHubPageIterator.java:93)
    at org.kohsuke.github.PagedIterator.fetch(PagedIterator.java:116)
    at org.kohsuke.github.PagedIterator.nextPageArray(PagedIterator.java:144)
    at org.kohsuke.github.PagedIterable.toArray(PagedIterable.java:85)
    at org.kohsuke.github.PagedIterable.toArray(PagedIterable.java:113)
    at org.kohsuke.github.GHRepository.getBranches(GHRepository.java:2626)
    at 
org.apache.nifi.github.GitHubRepositoryClient.lambda$getBranches$1(GitHubRepositoryClient.java:195)
    at 
org.apache.nifi.github.GitHubRepositoryClient.execute(GitHubRepositoryClient.java:421)
    at 
org.apache.nifi.github.GitHubRepositoryClient.getBranches(GitHubRepositoryClient.java:195)
    at 
org.apache.nifi.registry.flow.git.AbstractGitFlowRegistryClient.getBranches(AbstractGitFlowRegistryClient.java:156)
    at 
org.apache.nifi.registry.flow.StandardFlowRegistryClientNode.lambda$getBranches$0(StandardFlowRegistryClientNode.java:201)
    at 
org.apache.nifi.registry.flow.StandardFlowRegistryClientNode.execute(StandardFlowRegistryClientNode.java:314)
    at 
org.apache.nifi.registry.flow.StandardFlowRegistryClientNode.getBranches(StandardFlowRegistryClientNode.java:201)
    at 
org.apache.nifi.web.dao.impl.StandardFlowRegistryDAO.getBranchesForUser(StandardFlowRegistryDAO.java:120)
    ... 127 common frames omitted
Caused by: java.io.InterruptedIOException: null
    at org.kohsuke.github.RateLimitHandler$1.onError(RateLimitHandler.java:83)
    at org.kohsuke.github.RateLimitHandler.onError(RateLimitHandler.java:50)
    at org.kohsuke.github.GitHubClient.detectKnownErrors(GitHubClient.java:497)
    at org.kohsuke.github.GitHubClient.sendRequest(GitHubClient.java:464)
    ... 142 common frames omitted
Caused by: org.kohsuke.github.HttpException: API rate limit reached
    at org.kohsuke.github.RateLimitHandler.onError(RateLimitHandler.java:49)
    ... 144 common frames omitted {code}
 

To prevent this issue—and avoid waiting an hour before being able to push or 
pull from GitHub—it would be beneficial to have a way to adjust the GitHub API 
request rate when handling a large number of workflows. Alternatively, a manual 
synchronization button to trigger workflow updates from GitHub could also be a 
useful way to fix this behavior.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to