{"record":{"id":"c0cec47b3e474d2f","repo":"apache/incubator-seata","slug":"0109","errorCode":"0109","errorMessage":"msg:{msg}","messagePattern":"msg:\\{msg\\}","errorType":"exception","errorClass":"FrameworkException","httpStatus":null,"severity":"critical","filePath":"core/src/main/java/org/apache/seata/core/rpc/netty/AbstractNettyRemoting.java","lineNumber":390,"sourceCode":"        SocketAddress socketAddress = channel.remoteAddress();\n        String address = socketAddress.toString();\n        if (socketAddress.toString().indexOf(NettyClientConfig.getSocketAddressStartChar()) == 0) {\n            address = socketAddress\n                    .toString()\n                    .substring(NettyClientConfig.getSocketAddressStartChar().length());\n        }\n        return address;\n    }\n\n    private void channelWritableCheck(Channel channel, Object msg) {\n        int tryTimes = 0;\n        writabilityLock.lock();\n        try {\n            while (!channel.isWritable()) {\n                tryTimes++;\n                if (tryTimes > NettyClientConfig.getMaxNotWriteableRetry()) {\n                    destroyChannel(channel);\n                    throw new FrameworkException(\n                            \"msg:\" + ((msg == null) ? \"null\" : msg.toString()),\n                            FrameworkErrorCode.ChannelIsNotWritable);\n                }\n                try {\n                    writabilityCondition.await(NOT_WRITEABLE_CHECK_MILLS, TimeUnit.MILLISECONDS);\n                } catch (InterruptedException exx) {\n                    LOGGER.error(exx.getMessage());\n                    Thread.currentThread().interrupt();\n                    throw new FrameworkException(exx);\n                }\n            }\n        } finally {\n            writabilityLock.unlock();\n        }\n    }\n\n    /**\n     * Destroy channel.","sourceCodeStart":372,"sourceCodeEnd":408,"githubUrl":"https://github.com/apache/incubator-seata/blob/e01f97c6db397165050caa6764020410c2c8199a/core/src/main/java/org/apache/seata/core/rpc/netty/AbstractNettyRemoting.java#L372-L408","documentation":"channelWritableCheck blocks (on a lock + condition) while the Netty channel's send buffer is full; after NettyClientConfig.max-not-writeable-retry await cycles it destroys the channel and throws FrameworkException with error code ChannelIsNotWritable. It is backpressure: the peer is not reading fast enough, so Seata refuses to grow the outbound buffer unboundedly and drops the connection instead.","triggerScenarios":"Sending a large burst of RPC messages (batch undo logs, big branch registrations, merge-able requests) to a TC or client that stalls reading — GC pause on the peer, slow dbstore on TC, or a network path with bandwidth asymmetry; writable-buffer bytes high-water mark is exceeded and never recovers within the retry window.","commonSituations":"Large transactions generating multi-MB undo log payloads, TC db store slow (connection pool exhausted, lock contention), k8s network policy/traffic shaping throttling egress, or a misbehaving consumer holding the channel.","solutions":["Reduce payload size per message (batch limits, smaller undo logs per branch) so a single slow peer cannot fill the send buffer.","Address the slow reader: tune TC store throughput (db pool, disk), check peer GC/CPU throttling.","Increase netty write-buffer high-water mark / max-not-writeable-retry only as a buffer, not a fix; also verify client and TC bandwidth.","If recurrent, scale out TC nodes and rebalance transaction groups so no single channel carries the full burst."],"exampleFix":"# before\ntransport.max-not-writeable-retry default; huge batch undo in one tx\n# after\nsmaller branch batches +\ntransport.max-not-writeable-retry=64000 (buy time while fixing tc store)","handlingStrategy":"fallback","validationCode":"// before enqueuing a burst, check channel health/backpressure\nif (!channel.isActive() || !channel.isWritable()) {\n    routeToHealthyChannelOrSpool(); // do not pile onto a saturated channel\n}","typeGuard":"boolean canAcceptNow(Channel ch) { return ch.isActive() && ch.isWritable(); }","tryCatchPattern":"catch (FrameworkException e) {\n    if (e.getCode() == FrameworkErrorCode.ChannelIsNotWritable) {\n        // channel already destroyed: rebuild connection and replay idempotent messages with backoff\n        reconnectAndReplayIdempotent();\n    } else { throw e; }\n}","preventionTips":["Keep per-transaction undo payload small; batch branch operations","Monitor channel writability and outbound queue depth as leading indicators","Provision TC store/CPU for peak commit bursts; scale TC horizontally","Never disable the writable check — fix the slow peer instead"],"tags":["netty","backpressure","network","throughput","connection-reset"],"backgroundTag":null,"analyzedSha":"e01f97c6db397165050caa6764020410c2c8199a","analyzedAt":"2026-08-14T10:23:53.097Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}