Skip to content

WebClientRequestException & 403 Forbidden when calling Aiven Schema Registry (Karapace 4.1.3) #1449

@JulienBrunetDecathlon

Description

@JulienBrunetDecathlon

Issue submitter TODO list

  • I've looked up my issue in FAQ
  • I've searched for an already existing issues here
  • I've tried running main-labeled docker image and the issue still persists there
  • I'm running a supported version of the application which is listed here

Describe the bug (actual behavior)

WebClientRequestException & 403 Forbidden when calling Aiven Schema Registry (Karapace 4.1.3)

Description

When using Kafbat to fetch schemas from the Aiven Schema Registry (Karapace 4.1.3), requests fail in the application with errors, even though direct curl requests succeed.


Environment

  • Kafbat UI v1.3.0
  • Kafka version: Apache Kafka 3.8.1
  • Karapace version: 4.1.3
  • Kafka REST API (Karapace): Disabled
  • Schema Registry (Karapace): Enabled
  • Maintenance window: Tuesdays after 02:00:00 UTC

Steps to Reproduce

  1. Kafka cluster configuration in kafbat.yml:

    kafka:
      clusters:
      - bootstrapServers: https://public-kafka-XXXXXX.aivencloud.com:12668
        name: kafka-contrib
        schemaRegistry: https://public-kafka-XXXXXX.d.aivencloud.com:12661
        schemaRegistryAuth:
          username: avnadmin
          password: AXXXXX
  2. Request schemas via Kafbat:

    GET /api/clusters/kafka-contrib/schemas?page=1&perPage=25

    Observe the following error in the logs:

    org.springframework.web.reactive.function.client.WebClientRequestException: Connection prematurely closed BEFORE response
    Caused by: reactor.netty.http.client.PrematureCloseException
    
  3. Request schema subjects via curl:

    curl -v -u "avnadmin:AVNS_XXXXXX"      https://XXXXX.d.aivencloud.com:12661/subjects

    Expected result: 200 OK, list of subjects returned:

    ["test"]
  4. Request schema compatibility via Kafbat:

    GET /api/clusters/kafka-contrib/schemas/compatibility

    Results in:

    25-10-27 21:58:24,037 ERROR [reactor-http-nio-3] ... 500 Server Error for HTTP GET "/api/clusters/kafka-contrib/schemas/compatibility"
    org.springframework.web.reactive.function.client.WebClientResponseException$Forbidden: 403 Forbidden from GET https://public-kafka-contrib-XXXXXX.d.aivencloud.com:12661/config
    

Expected Behavior

  • Schemas should be retrieved successfully via Kafbat without premature connection closure.
  • Compatibility level should be retrievable without 403 Forbidden.

Observed Behavior

  • WebClientRequestException: Connection prematurely closed BEFORE response when fetching schemas.
  • WebClientResponseException$Forbidden: 403 Forbidden when fetching global compatibility config.
  • Direct curl requests to the Schema Registry succeed.

Additional Information

  • TLS / SSL configured in WebClient via Reactor Netty.
  • Schema Registry endpoint uses HTTPS and Basic Authentication.
  • The 403 error occurs when calling /config endpoint for compatibility level.
  • Karapace version 4.1.3 may handle certain endpoints differently than the Confluent Schema Registry.

Expected behavior

["test"]

Your installation details

v1.3.0

auth:
  oauth2:
    client:
      claude:
        authorizationGrantType: authorization_code
        authorizationUri: https://idp.claude.com/as/authorization.oauth2
        clientId: XXXX
        clientName: Claude.DO
        clientSecret: XXXXXX
        customParams:
          type: oauth
          roles-field: support_groups
        issuerUri: https://idp.claude.com
        jwkSetUri: https://idp.claude.com
        provider: decathlon
        redirectUri: http://localhost:8080/login/oauth2/code/claude
        scope: !!set
          openid: null
          profile: null
          email: null
          support_groups: null
        tokenUri: https://idp.claude.com/as/token.oauth2
        userInfoUri: https://idp.claude.com/as/userinfo.openid
        userNameAttribute: email
  type: OAUTH2
kafka:
  clusters:
  - bootstrapServers: public-kafka-XXXXXXX.d.aivencloud.com:12668
    consumerProperties: {}
    kafkaConnect: []
    masking: []
    name: kafka-contrib
    producerProperties: {}
    properties:
      security.protocol: SSL
      ssl.keystore.type: PKCS12
      ssl.truststore.location: /app/ssl/kafka-contrib.client.truststore.jks
      ssl.keystore.password: nochange
      ssl.keystore.location: /app/ssl/kafka-contrib.client.keystore.p12
      ssl.truststore.password: nochange
      ssl.truststore.type: JKS
    readOnly: false
    schemaRegistry: https://public-kafka-XXXXXX.d.aivencloud.com:12661
    schemaRegistryAuth:
      password: XXXXXXXX
      username: avnadmin
    serde: []
rbac:
  roles:
  - clusters:
    - kafka-contrib
    name: CS-RUNAPI-teams
    permissions:
    - actions:
      - VIEW
      - EDIT
      resource: APPLICATIONCONFIG
    - actions:
      - VIEW
      - EDIT
      resource: CLUSTERCONFIG
    - actions:
      - VIEW
      - CREATE
      - EDIT
      - DELETE
      - MESSAGES_READ
      - MESSAGES_PRODUCE
      - MESSAGES_DELETE
      resource: TOPIC
      value: .*
    - actions:
      - VIEW
      - DELETE
      - RESET_OFFSETS
      resource: CONSUMER
      value: .*
    - actions:
      - VIEW
      - CREATE
      - EDIT
      - DELETE
      resource: SCHEMA
      value: .*
    - actions:
      - VIEW
      - CREATE
      - EDIT
      - DELETE
      resource: CONNECT
      value: .*
    - actions:
      - VIEW
      - EDIT
      resource: ACL
    subjects:
    - isRegex: false
      provider: OAUTH
      type: role
      value: CS-RUNAPI
  - clusters:
    - kafka-contrib
    name: default-read-only
    permissions:
    - actions:
      - VIEW
      resource: TOPIC
      value: .*
    subjects:
    - isRegex: false
      provider: OAUTH
      type: user
      value: .*
webclient: {}

Steps to reproduce

Steps to Reproduce

  1. Kafka cluster configuration in kafbat.yml:

    kafka:
      clusters:
      - bootstrapServers: https://public-kafka-XXXXXX.aivencloud.com:12668
        name: kafka-contrib
        schemaRegistry: https://public-kafka-XXXXXX.d.aivencloud.com:12661
        schemaRegistryAuth:
          username: avnadmin
          password: AXXXXX
  2. Request schemas via Kafbat:

    GET /api/clusters/kafka-contrib/schemas?page=1&perPage=25

    Observe the following error in the logs:

    org.springframework.web.reactive.function.client.WebClientRequestException: Connection prematurely closed BEFORE response
    Caused by: reactor.netty.http.client.PrematureCloseException
    
  3. Request schema subjects via curl:

    curl -v -u "avnadmin:AVNS_XXXXXX"      https://XXXXX.d.aivencloud.com:12661/subjects

    Expected result: 200 OK, list of subjects returned:

    ["test"]
  4. Request schema compatibility via Kafbat:

    GET /api/clusters/kafka-contrib/schemas/compatibility

    Results in:

    25-10-27 21:58:24,037 ERROR [reactor-http-nio-3] ... 500 Server Error for HTTP GET "/api/clusters/kafka-contrib/schemas/compatibility"
    org.springframework.web.reactive.function.client.WebClientResponseException$Forbidden: 403 Forbidden from GET https://public-kafka-contrib-XXXXXX.d.aivencloud.com:12661/config
    

Expected Behavior

  • Schemas should be retrieved successfully via Kafbat without premature connection closure.
  • Compatibility level should be retrievable without 403 Forbidden.

Observed Behavior

  • WebClientRequestException: Connection prematurely closed BEFORE response when fetching schemas.
  • WebClientResponseException$Forbidden: 403 Forbidden when fetching global compatibility config.
  • Direct curl requests to the Schema Registry succeed.

Additional Information

  • TLS / SSL configured in WebClient via Reactor Netty.
  • Schema Registry endpoint uses HTTPS and Basic Authentication.
  • The 403 error occurs when calling /config endpoint for compatibility level.
  • Karapace version 4.1.3 may handle certain endpoints differently than the Confluent Schema Registry.

Screenshots

No response

Logs

2025-10-27 21:58:21,535 INFO [boundedElastic-7] o.a.k.c.u.AppInfoParser: Kafka version: 7.9.0-ccs 2025-10-27 21:58:21,535 INFO [boundedElastic-7] o.a.k.c.u.AppInfoParser: Kafka commitId: ebe6df624d6bc758 2025-10-27 21:58:21,535 INFO [boundedElastic-7] o.a.k.c.u.AppInfoParser: Kafka startTimeMs: 1761602301535 2025-10-27 21:58:22,131 DEBUG [parallel-2] i.k.u.s.ClustersStatisticsScheduler: Metrics updated for cluster: kafka-contrib 2025-10-27 21:58:22,468 DEBUG [reactor-http-nio-4] i.k.u.s.r.e.OauthAuthorityExtractor: Principal name is: [[email protected]] 2025-10-27 21:58:22,469 DEBUG [reactor-http-nio-4] i.k.u.s.r.e.OauthAuthorityExtractor: Matched roles by username: [] 2025-10-27 21:58:22,469 DEBUG [reactor-http-nio-4] i.k.u.s.r.e.OauthAuthorityExtractor: Token's groups: [CS-RUNAPI,CS-JEAN....] 2025-10-27 21:58:22,469 DEBUG [reactor-http-nio-4] i.k.u.s.r.e.OauthAuthorityExtractor: Matched group roles: [CS-RUNAPI-teams] 2025-10-27 21:58:24,037 ERROR [reactor-http-nio-3] o.s.b.a.w.r.e.AbstractErrorWebExceptionHandler: [eab277d2-330] 500 Server Error for HTTP GET "/api/clusters/kafka-contrib/schemas/compatibility" org.springframework.web.reactive.function.client.WebClientResponseException$Forbidden: 403 Forbidden from GET https://public-kafka-contrib-XXXXXX.d.aivencloud.com:12661/config at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:323) Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: Error has been observed at the following site(s): *__checkpoint ⇢ 403 FORBIDDEN from GET https://public-kafka-XXXX.d.aivencloud.com:12661/config [DefaultWebClient] *__checkpoint ⇢ Handler io.kafbat.ui.controller.SchemasController#getGlobalSchemaCompatibilityLevel(String, ServerWebExchange) [DispatcherHandler] *__checkpoint ⇢ io.kafbat.ui.config.CorsGlobalConfiguration$$Lambda/0x000000010176d3e0 [DefaultWebFilterChain] *__checkpoint ⇢ io.kafbat.ui.config.ReadOnlyModeFilter [DefaultWebFilterChain] *__checkpoint ⇢ io.kafbat.ui.config.CustomWebFilter [DefaultWebFilterChain] *__checkpoint ⇢ AuthorizationWebFilter [DefaultWebFilterChain] *__checkpoint ⇢ ExceptionTranslationWebFilter [DefaultWebFilterChain] *__checkpoint ⇢ LogoutWebFilter [DefaultWebFilterChain] *__checkpoint ⇢ ServerRequestCacheWebFilter [DefaultWebFilterChain] *__checkpoint ⇢ SecurityContextServerWebExchangeWebFilter [DefaultWebFilterChain] *__checkpoint ⇢ LogoutPageGeneratingWebFilter [DefaultWebFilterChain] *__checkpoint ⇢ LoginPageGeneratingWebFilter [DefaultWebFilterChain] *__checkpoint ⇢ StaticFileWebFilter [DefaultWebFilterChain] *__checkpoint ⇢ DefaultResourcesWebFilter [DefaultWebFilterChain] *__checkpoint ⇢ OAuth2LoginAuthenticationWebFilter [DefaultWebFilterChain] *__checkpoint ⇢ OAuth2AuthorizationRequestRedirectWebFilter [DefaultWebFilterChain] *__checkpoint ⇢ ReactorContextWebFilter [DefaultWebFilterChain] *__checkpoint ⇢ HttpHeaderWriterWebFilter [DefaultWebFilterChain] *__checkpoint ⇢ ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain] *__checkpoint ⇢ org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain] *__checkpoint ⇢ HTTP GET "/api/clusters/kafka-contrib/schemas/compatibility" [ExceptionHandlingWebHandler] Original Stack Trace: at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:323) at org.springframework.web.reactive.function.client.DefaultClientResponse.lambda$createException$1(DefaultClientResponse.java:214) at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:106) at reactor.core.publisher.FluxOnErrorReturn$ReturnSubscriber.onNext(FluxOnErrorReturn.java:162) at reactor.core.publisher.FluxDefaultIfEmpty$DefaultIfEmptySubscriber.onNext(FluxDefaultIfEmpty.java:122) at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:129) at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:107) at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onNext(FluxMapFuseable.java:299) at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onNext(FluxFilterFuseable.java:337) at reactor.core.publisher.Operators$BaseFluxToMonoOperator.completePossiblyEmpty(Operators.java:2096) at reactor.core.publisher.MonoCollect$CollectSubscriber.onComplete(MonoCollect.java:145) at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:144) at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:260) at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:144) at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:413) at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:455) at reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:509) at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:821) at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:115) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318) at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1519) at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1377) at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1428) at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:530) at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:469) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1357) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:868) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:796) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:732) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:658) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:998) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:1583) 2025-10-27 21:58:25,098 ERROR [reactor-http-nio-3] o.s.b.a.w.r.e.AbstractErrorWebExceptionHandler: [eab277d2-332] 500 Server Error for HTTP GET "/api/clusters/kafka-contrib/schemas/compatibility" org.springframework.web.reactive.function.client.WebClientResponseException$Forbidden: 403 Forbidden

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions