Skip to content

[FLINK-39103][runtime] Tolerate errors when recycling buffer from input channel notification if it had errors already#27624

Merged
rkhachatryan merged 2 commits intoapache:masterfrom
rkhachatryan:f39103
Feb 20, 2026
Merged

[FLINK-39103][runtime] Tolerate errors when recycling buffer from input channel notification if it had errors already#27624
rkhachatryan merged 2 commits intoapache:masterfrom
rkhachatryan:f39103

Conversation

@rkhachatryan
Copy link
Contributor

@rkhachatryan rkhachatryan commented Feb 17, 2026

The first 3 commits are from #27619 - please ignore them while reviewing.

Example failure stack trace:

java.lang.RuntimeException: org.apache.flink.runtime.io.network.netty.exception.RemoteTransportException: Error at remote task manager 'localhost/127.0.0.1:40903 [ 8b99efa6-f87f-4fba-9d9d-9b8497d249fa ] '.
	at org.apache.flink.util.ExceptionUtils.rethrow(ExceptionUtils.java:321) ~[flink-core-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.runtime.io.network.partition.consumer.BufferManager.recycle(BufferManager.java:237) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.runtime.io.network.buffer.NetworkBuffer.deallocate(NetworkBuffer.java:189) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.shaded.netty4.io.netty.buffer.AbstractReferenceCountedByteBuf.handleRelease(AbstractReferenceCountedByteBuf.java:151) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:141) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.runtime.io.network.buffer.NetworkBuffer.recycleBuffer(NetworkBuffer.java:161) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.runtime.io.network.api.serialization.SpillingAdaptiveSpanningRecordDeserializer.clear(SpillingAdaptiveSpanningRecordDeserializer.java:140) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.streaming.runtime.io.AbstractStreamTaskNetworkInput.releaseDeserializer(AbstractStreamTaskNetworkInput.java:328) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.streaming.runtime.io.AbstractStreamTaskNetworkInput.close(AbstractStreamTaskNetworkInput.java:320) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.streaming.runtime.io.StreamTaskNetworkInput.close(StreamTaskNetworkInput.java:142) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.streaming.runtime.io.StreamOneInputProcessor.close(StreamOneInputProcessor.java:88) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.streaming.runtime.tasks.StreamTask.cleanUpInternal(StreamTask.java:1112) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.util.IOUtils.closeAll(IOUtils.java:257) ~[flink-core-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.core.fs.AutoCloseableRegistry.doClose(AutoCloseableRegistry.java:83) ~[flink-core-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.util.AbstractAutoCloseableRegistry.close(AbstractAutoCloseableRegistry.java:127) ~[flink-core-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.streaming.runtime.tasks.StreamTask.cleanUp(StreamTask.java:1103) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.runtime.taskmanager.Task.lambda$restoreAndInvoke$2(Task.java:972) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.runtime.taskmanager.Task.runWithSystemExitMonitoring(Task.java:987) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.runtime.taskmanager.Task.lambda$restoreAndInvoke$3(Task.java:972) [flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.util.IOUtils.closeAll(IOUtils.java:257) ~[flink-core-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.core.fs.AutoCloseableRegistry.doClose(AutoCloseableRegistry.java:83) ~[flink-core-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.util.AbstractAutoCloseableRegistry.close(AbstractAutoCloseableRegistry.java:127) ~[flink-core-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.runtime.taskmanager.Task.doRun(Task.java:808) [flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.runtime.taskmanager.Task.run(Task.java:579) [flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at java.base/java.lang.Thread.run(Thread.java:833) [?:?]
Caused by: org.apache.flink.runtime.io.network.netty.exception.RemoteTransportException: Error at remote task manager 'localhost/127.0.0.1:40903 [ 8b99efa6-f87f-4fba-9d9d-9b8497d249fa ] '.
	at org.apache.flink.runtime.io.network.netty.CreditBasedPartitionRequestClientHandler.decodeMsg(CreditBasedPartitionRequestClientHandler.java:333) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.runtime.io.network.netty.CreditBasedPartitionRequestClientHandler.channelRead(CreditBasedPartitionRequestClientHandler.java:197) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.shaded.netty4.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:356) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.runtime.io.network.netty.NettyMessageClientDecoderDelegate.channelRead(NettyMessageClientDecoderDelegate.java:112) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.shaded.netty4.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:356) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1429) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:918) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:794) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.channel.epoll.AbstractEpollChannel$AbstractEpollUnsafe.handle(AbstractEpollChannel.java:482) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.channel.epoll.EpollIoHandler$DefaultEpollIoRegistration.handle(EpollIoHandler.java:317) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.channel.epoll.EpollIoHandler.processReady(EpollIoHandler.java:514) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.channel.epoll.EpollIoHandler.run(EpollIoHandler.java:459) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.channel.SingleThreadIoEventLoop.runIo(SingleThreadIoEventLoop.java:225) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.channel.SingleThreadIoEventLoop.run(SingleThreadIoEventLoop.java:196) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:1193) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	... 1 more
Caused by: org.apache.flink.runtime.io.network.partition.ProducerFailedException: java.lang.Exception: java.lang.Exception: Artificial Failure
	at org.apache.flink.runtime.io.network.partition.PipelinedSubpartitionView.getFailureCause(PipelinedSubpartitionView.java:96) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.runtime.io.network.netty.CreditBasedSequenceNumberingViewReader.getFailureCause(CreditBasedSequenceNumberingViewReader.java:282) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.runtime.io.network.netty.PartitionRequestQueue.writeAndFlushNextMessageIfPossible(PartitionRequestQueue.java:325) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.runtime.io.network.netty.PartitionRequestQueue.enqueueAvailableReader(PartitionRequestQueue.java:126) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.runtime.io.network.netty.PartitionRequestQueue.addCreditOrResumeConsumption(PartitionRequestQueue.java:175) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.runtime.io.network.netty.PartitionRequestServerHandler.channelRead0(PartitionRequestServerHandler.java:115) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.runtime.io.network.netty.PartitionRequestServerHandler.channelRead0(PartitionRequestServerHandler.java:42) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.shaded.netty4.io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:356) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:356) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1429) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:918) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:794) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.channel.epoll.AbstractEpollChannel$AbstractEpollUnsafe.handle(AbstractEpollChannel.java:482) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.channel.epoll.EpollIoHandler$DefaultEpollIoRegistration.handle(EpollIoHandler.java:317) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.channel.epoll.EpollIoHandler.processReady(EpollIoHandler.java:514) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.channel.epoll.EpollIoHandler.run(EpollIoHandler.java:459) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.channel.SingleThreadIoEventLoop.runIo(SingleThreadIoEventLoop.java:225) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.channel.SingleThreadIoEventLoop.run(SingleThreadIoEventLoop.java:196) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:1193) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	at org.apache.flink.shaded.netty4.io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[flink-shaded-netty-4.2.6.Final-21.0.jar:?]
	... 1 more
Caused by: org.apache.flink.util.SerializedThrowable: java.lang.Exception: Artificial Failure
	at org.apache.flink.test.checkpointing.utils.FailingSource.run(FailingSource.java:111) ~[test-classes/:?]
	at org.apache.flink.streaming.api.operators.StreamSource.run(StreamSource.java:107) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.streaming.api.operators.StreamSource.run(StreamSource.java:68) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]
	at org.apache.flink.streaming.runtime.tasks.SourceStreamTask$LegacySourceFunctionThread.run(SourceStreamTask.java:346) ~[flink-runtime-2.3-SNAPSHOT.jar:2.3-SNAPSHOT]

@flinkbot
Copy link
Collaborator

flinkbot commented Feb 17, 2026

CI report:

Bot commands The @flinkbot bot supports the following commands:
  • @flinkbot run azure re-run the last Azure build

@@ -216,6 +221,10 @@ public void recycle(MemorySegment segment) {
if (inputChannel.isReleased()) {
globalPool.recycleUnpooledMemorySegments(Collections.singletonList(segment));
return;
} else if (inputChannel.hasError()) {
LOG.warn("Input channel has errors - recycling the buffer");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this warn result in e2e test failure as "unexpected error" or do we only filter for ERROR level there?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC the script greps errors, not warnings, so it should be fine.

Copy link
Contributor

@Izeren Izeren left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @rkhachatryan, I have left a couple of comments for better understanding of the problem

@@ -346,6 +346,11 @@ public long unsynchronizedGetSizeOfQueuedBuffers() {
*/
public void notifyRequiredSegmentId(int subpartitionId, int segmentId) throws IOException {}

/** Whether this input channel has encountered error. */
public boolean hasError() {
return cause.get() != null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it is not too complicated would be good to write a dedicated unit test for new public method

Copy link
Contributor Author

@rkhachatryan rkhachatryan Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, I just wanted to agree on the approach first.
Other approaches are passing ignoreErrors to notifyBufferAvailable or ignoring errors coming from it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a test

@@ -216,6 +221,10 @@ public void recycle(MemorySegment segment) {
if (inputChannel.isReleased()) {
globalPool.recycleUnpooledMemorySegments(Collections.singletonList(segment));
return;
} else if (inputChannel.hasError()) {
LOG.warn("Input channel has errors - recycling the buffer");
globalPool.recycleUnpooledMemorySegments(Collections.singletonList(segment));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For my understanding, does every segment have only 1 input channel?
Can it happen that we would call recycleUnpooledMemorySegments on the same segment twice? If yes, is this call idempotent?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, at any given time each memory segment has only one owner, and recycling it twice would cause an error.

@rkhachatryan rkhachatryan force-pushed the f39103 branch 2 times, most recently from 0042631 to 7d35eec Compare February 17, 2026 15:45
Comment on lines +327 to +328
final boolean hadError =
checkpointedInputGate.getChannel(channelInfo.getInputChannelIdx()).hasError();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In theory, recycling the buffer can also fail for other reason:

if (inputChannel.isReleased()) {
  globalPool.recycleUnpooledMemorySegments(Collections.singletonList(segment));

But I think global pool failure shouldn't be ignored.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I share the same concern you mentioned.

The current catch (Exception e) + if (hadError) would swallow all exceptions from releaseDeserializer, not just the channel error. If e.g. globalPool.recycleUnpooledMemorySegments fails while hadError=true, that failure is silently lost.

And it is dangerous if introducing new exception in the future.

@rkhachatryan rkhachatryan marked this pull request as ready for review February 17, 2026 15:49
@rkhachatryan rkhachatryan requested a review from Izeren February 17, 2026 15:50
@rkhachatryan
Copy link
Contributor Author

CI failures seem unrelated

@github-actions github-actions bot added the community-reviewed PR has been reviewed by the community. label Feb 18, 2026
Copy link
Contributor

@Izeren Izeren left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, I have added a few more comments, PTAL

Copy link
Member

@1996fanrui 1996fanrui left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According the inline comment, I wonder if we should fix this at a different layer. Tracing the call chain:

BufferManager.recycle(segment)
  → buffer added back to queue              ← already recycled successfully
  → inputChannel.notifyBufferAvailable(1)    ← credit notification
    → notifyCreditAvailable()
      → checkPartitionRequestQueueInitialized()
        → checkError() → throws

The buffer is already recycled at that point. The failure comes from notifying credit to a producer whose connection is already dead — which is unnecessary.

What about skipping credit notification for errored channels instead?

// RemoteInputChannel.java
public void notifyBufferAvailable(int numAvailableBuffers) throws IOException {
    if (hasError()) {
        return;
    }
    if (numAvailableBuffers > 0 && unannouncedCredit.getAndAdd(numAvailableBuffers) == 0) {
        notifyCreditAvailable();
    }
}

This way: (1) buffer recycling is not affected, (2) global pool errors are not affected (they happen before notifyBufferAvailable in BufferManager.recycle), and (3) all code paths that recycle buffers are covered, not just close().

Comment on lines +327 to +328
final boolean hadError =
checkpointedInputGate.getChannel(channelInfo.getInputChannelIdx()).hasError();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I share the same concern you mentioned.

The current catch (Exception e) + if (hadError) would swallow all exceptions from releaseDeserializer, not just the channel error. If e.g. globalPool.recycleUnpooledMemorySegments fails while hadError=true, that failure is silently lost.

And it is dangerous if introducing new exception in the future.

@rkhachatryan
Copy link
Contributor Author

According the inline comment, I wonder if we should fix this at a different layer.

Yeah, I'm not sure which level is better to fix this issue.

In the original version, I fixed it at a lower level as you suggest. But there, it affects other notification paths besides of Task cleanup - which probably should not tolerate this error.

In the current version, we're certain that it's Task cleanup, so the error can be ignored (if the channel errored already). However, it can be some error not related to channel.

Maybe the middle ground is to catch it StreamTaskNetworkInput but check explicitly that it's a RemoteTransportException.
Something like

} catch (Exception e) {
    if (hadError && 
        ExceptionUtils.findThrowable(e, RemoteTransportException.class).isPresent()) {

WDYT?

@1996fanrui
Copy link
Member

In the original version, I fixed it at a lower level as you suggest. But there, it affects other notification paths besides of Task cleanup - which probably should not tolerate this error.

Thanks for the valuable input! I did not test it, so not sure if the notification paths is suitable, or they can be changed as well.

In the current version, we're certain that it's Task cleanup, so the error can be ignored (if the channel errored already). However, it can be some error not related to channel.

Maybe the middle ground is to catch it StreamTaskNetworkInput but check explicitly that it's a RemoteTransportException. Something like

} catch (Exception e) {
    if (hadError && 
        ExceptionUtils.findThrowable(e, RemoteTransportException.class).isPresent()) {

WDYT?

The new proposal makes sense to me, it only suppresses the RemoteTransportException.

…orresponding channel already had errors

On cleanup, deserializer recycles its buffers, potentially notifying the input channel.

However, if the input channel has encountered an error (such as RemoteTransportException);
then notification will fail which might cause the whol cleanup to fail
and lead to TM shutdown.
@rkhachatryan rkhachatryan requested review from 1996fanrui and Izeren and removed request for Izeren and pnowojski February 20, 2026 15:21
@rkhachatryan
Copy link
Contributor Author

Thanks for the reviews @1996fanrui @Izeren!

The previous build failed due to FLINK-38613.

I'm going to proceed with merging

@rkhachatryan rkhachatryan merged commit 45c62ca into apache:master Feb 20, 2026
@rkhachatryan rkhachatryan deleted the f39103 branch February 20, 2026 15:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community-reviewed PR has been reviewed by the community.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

Comments