Rohit
09/08/2026, 7:14 AMcurrent node is not added to the cluster) due to stale Feb-dated identity never joined under the current cluster. Fixed the crash loop by:
• ALTER SYSTEM DROP FOLLOWER → wipe meta_dir → restart with --helper <leader>:9011 → ALTER SYSTEM ADD FOLLOWER
Follower now joins successfully (shows Alive: true, gets a fresh identity), but ReplayedJournalId freezes at exactly 9363239 and never moves — while the leader's own ReplayedJournalId keeps climbing normally (currently ~9.51M+). Repeated this full wipe-and-rejoin 3 times, same exact frozen number every time.
Already ruled out: networking (leader ports confirmed reachable), log4j/permissions (found and fixed separately, didn't help), stale process/PID, GC/memory pressure (GC logs clean).
Questions:
1. Does 9363239 mean anything specific — a checkpoint boundary, a schema-change entry, something BDB-JE handles specially?
2. Could shared-loopback BE topology (all 3 BEs on 127.0.0.1, different ports) be causing replica/tablet-related journal entries to fail replay for a fresh follower?
3. Is a rm -rf meta_dir wipe actually sufficient, or can an FE that was ever part of an older cluster incarnation (different ClusterId history, back from Feb) retain some other cached state that blocks it even after wipe?
4. Any way to directly inspect the leader's edit log content at that journal ID to see what operation is actually there?Rocky
09/08/2026, 7:14 AMReplayedJournalId after a full wipe—strongly indicates that the follower is encountering a blocking operation or a poison pill entry in the edit log provided by the leader.
1. Significance of ID 9363239
While this specific number is unique to your cluster, freezing at a fixed ID usually points to one of two things:
* External Metadata Blocking: A known issue in StarRocks (e.g., Issue #73832) occurs when the replayer thread tries to load metadata for an external catalog (like Hive or Iceberg) that is now unreachable. The EditLog.loadJournal thread calls getTable(), which blocks on a network timeout, effectively halting all further replay. Since your cluster was dormant since February, any external HMS/Glue links might be stale or unreachable.
* Heavy Schema/Metadata Change: It could be a checkpoint boundary or a very large OP_SAVE_NEXTID or tablet-heavy operation that is taking an exceptionally long time to process in memory, though usually, these eventually time out or log an error.
2. Loopback/Colocated Topology
A shared-loopback topology is likely not the cause of the replay freeze. Journal replay is an internal FE process that updates the GlobalStateMgr in memory. While loopback IPs can cause issues with tablet report consistency or BE-to-FE heartbeats, they don't typically block the BDB-JE replayer thread.
* Verification: Run jstack <FE_PID> | grep -A 20 "replayer" on the stuck follower. If you see the thread waiting on a network socket or an external catalog call (e.g., com.starrocks.connector...), the topology isn't the issue—the external dependency is.
3. Is rm -rf meta_dir sufficient?
Yes, rm -rf meta_dir completely resets the local FE's state. The fact that it gets stuck at the same ID every time confirms that the problem is in the edit log stream it is receiving from the leader. The follower pulls the history from the leader's BDB-JE database; if there is a "corrupt" or "blocking" entry at that ID in the leader's store, every fresh follower will hit it.
4. How to inspect the edit log content
To see exactly what is at that journal ID, use the following methods:
* SQL (on Leader):
sql
SHOW PROC "/journal";
This shows the range and status of journals. However, it won't show the specific operation type per ID.
* BDB-JE Tool (Manual):
You can use the BDB-JE utility to dump the raw logs. Locate the BDB-JE jar in your fe/lib directory (e.g., starrocks-bdb-je-18.3.16.jar):
bash
java -jar fe/lib/starrocks-bdb-je-*.jar DbPrintLog -h fe/meta/bdb/ -vd
Search the output for the VLSN/Journal ID.
* FE Logs: Set the BDB log level to FINEST in fe.conf on the follower to see the last operation attempted before the freeze:
properties
bdbje_log_level = FINEST
Recommended Fixes
1. Skip the Bad Journal (Emergency): If you identify that the entry is non-critical (like a stats update), you can force the follower to skip it by adding this to the follower's `fe.conf`:
properties
metadata_journal_skip_bad_journal_ids = 9363239
2. Check External Catalogs: If you have external catalogs, ensure the FE can reach the Hive Metastore or AWS Glue. If they are no longer needed, you may need to drop them from the leader.
3. Jstack is Key: The most definitive way to solve this is a jstack of the replayer thread. If the thread is in RUNNABLE but stuck in a <http://java.net|java.net> or connector package, you've found the blocker.
References
• administration/Meta_recovery.mdRohit
09/08/2026, 7:20 AM401 Unauthorized as expected). But the follower (FE2) still logs Connection refused on its internal getFeNodeTypeAndNameFromHelpers() call to the helper. This means FE2 itself may be attempting the connection against the wrong IP or port internally — possibly its own interface (127.0.0.2) instead of the helper's (127.0.0.1), or the raw edit-log port (9011) instead of the HTTP port (8031). Is there a known code path or config interaction (e.g., priority_networks, IPv6-related address resolution skipping we're seeing in logs) that could cause the helper HTTP call to target the wrong address on a follower during first-join, on 3.5.13?Rocky
09/08/2026, 7:20 AMReplayedJournalId freezing while the node is Alive often indicates a failure in the Image (Checkpoint) Sync process. When a follower is significantly behind or hits a specific metadata boundary, it stops replaying incremental logs and attempts to download a full metadata image from the leader via the HTTP port (default 8030).
The Connection refused error in getFeNodeTypeAndNameFromHelpers() confirms that FE2 is failing to reach the helper's HTTP interface, which is required for this synchronization.
1. Why it targets the "wrong" address
When you start an FE with --helper <IP>:<Port>, the <Port> you provide is the edit_log_port (9010/9011). However, the FE needs to perform HTTP calls for metadata. It attempts to "guess" or look up the HTTP port:
* The Offset Guess: If you are using non-default ports, the follower might be trying to reach the leader's HTTP port at an incorrect address.
* Advertisement Mismatch: Once the follower makes initial contact via the edit_log_port, the leader sends its own "advertised" address. If the leader hasn't explicitly bound to 127.0.0.1 via priority_networks, it may be advertising its AWS internal IP (e.g., 10.0.x.x).
* Loopback Conflict: If your FEs are on 127.0.0.1, 127.0.0.2, etc., but priority_networks is not set, StarRocks may default to the first available non-loopback interface or bind all FEs to the same 127.0.0.1 interface, causing port collisions or routing failures.
2. The priority_networks Fix
To fix this in a colocated loopback setup, you must force each FE to recognize and advertise its specific loopback IP.
On FE2 (and similarly for others), update `fe.conf`:
properties
# Force FE to bind only to its assigned loopback IP
priority_networks = 127.0.0.2/32
# Ensure the HTTP port is explicitly defined and matching your setup
http_port = 8031
_Note: If all FEs share 127.0.0.1 but use different ports, set priority_networks = 127.0.0.1/32._
3. Check for "Image Transfer" logs
Search your fe.log on the follower for ImageTransferException or Transfer image. If the follower is stuck at a fixed ID, you will likely see:
failed to download image from http://<leader_ip>:<port>/image...
The <leader_ip> in that log is the address the follower is actually trying to use. If that IP is not 127.0.0.1, the connection will be refused.
4. Direct Inspection of the Leader's Advertisement
Run this on the Leader:
sql
SHOW PROC '/frontends';
Look at the IP and HttpPort columns. If the Leader's IP is listed as an AWS internal IP (e.g., 172.x.x.x), the follower will attempt to connect to that IP. In a loopback-only or restricted network setup, this will fail. You must restart the Leader with priority_networks set to 127.0.0.1/32 so it registers itself with the correct address.
5. Why 9363239?
This ID likely marks the point where the Leader's BDB-JE log has been "cleaned" (purged) and the Follower is forced to transition from replaying logs to downloading a Checkpoint Image. Since the HTTP connection is refused, it can never get the image to move past that ID.
Summary Checklist:
1. Verify the Leader's IP in SHOW PROC '/frontends'.
2. Explicitly set priority_networks on all FEs to the loopback address.
3. Ensure java.net.preferIPv4Stack=true is in fe.conf (under JAVA_OPTS) to prevent IPv6 resolution issues on loopback.
4. Restart the Leader first, then the Follower.
References
• administration/Meta_recovery.md
• knowledge/trouble_shooting/fe_deadlock_problems.mdRohit
09/08/2026, 7:24 AMSHOW CATALOGS shows only default_catalog
• *Leader IP/advertisement:*`SHOW PROC '/frontends'` confirms leader is correctly registered as 127.0.0.1, not an AWS internal IP
• *Leader HTTP reachability:*`curl -v http://127.0.0.1:8031/` from the same box returns 401 Unauthorized instantly — the HTTP port is fully up and responding correctly
New finding via `jstack`: the follower's main thread never gets past NodeMgr.getClusterIdAndRoleOnStartup() — it's stuck sleeping/retrying every 5 seconds, indefinitely. GlobalStateMgr.initialize() never returns, so no replayer thread is ever created. This means ReplayedJournalId freezing at a fixed value isn't a replay problem — replay never starts, because the initial cluster-join handshake itself never succeeds.
The core mystery: the follower's internal JVM HTTP client logs Connection refused when calling the helper (getFeNodeTypeAndNameFromHelpers()), on the same host/port (127.0.0.1:8031) that curl reaches successfully from the same machine, same moment. So the leader's HTTP endpoint is definitely up and reachable at the OS level — but the follower's own JVM can't connect to it internally.
This has been consistent across 3 full clean wipe-and-rejoin attempts (DROP FOLLOWER → wipe meta_dir → restart with --helper → ADD FOLLOWER), same failure every time.
Question: given the leader's HTTP port is confirmed reachable externally (curl) but the follower's own JVM reports connection-refused on what should be the same call — could this be an IPv4/IPv6 socket resolution issue specific to the JVM (e.g., java.net.preferIPv4Stack not set, causing the follower to attempt the call over a different address family or interface than curl uses)? Is there a way to confirm which literal socket address the follower's JVM is targeting for this call, or a config flag that forces it to match what curl successfully reaches?
Current state: leader (FE1) is fully healthy and serving production without issue. Followers (FE2/FE3) are not joining — no outage, but zero redundancy currently.Rocky
09/08/2026, 7:25 AMConnection refused on a loopback address—is a classic sign of JVM-level networking environmental issues, especially in colocated or loopback-heavy setups.
Given that your ReplayedJournalId stops at the same number (9363239) every time, this ID likely represents the Checkpoint Image version the follower managed to download (or the end of the logs available before a mandatory image sync). The follower is now trying to contact the leader via HTTP to fetch either the next log or a newer image, and that's where it's failing.
1. The Literal Address Mystery
The most likely reason the JVM fails while curl works is IPv6 vs IPv4 resolution. Even if you specify 127.0.0.1, the JVM may attempt to resolve the "loopback" or handle the socket via the IPv6 stack (trying ::1) unless explicitly told otherwise.
Action: Ensure your fe.conf (under JAVA_OPTS) has the following flag. StarRocks usually includes this, but if it was stripped or overwritten in your AWS setup, it will cause exactly this behavior:
properties
-Djava.net.preferIPv4Stack=true
If you are using localhost anywhere in your config or helper string, change it to the literal 127.0.0.1.
2. Port Discovery/Mismatch
StarRocks FEs use the edit_log_port (9010/9011) for the BDB-JE handshake, but they use the http_port (8030/8031) for metadata sync.
* When a follower starts, it uses its own http_port configuration as a guess to contact the helper's HTTP port.
* The Problem: If FE1 (Leader) is listening on 8031, but FE2 (Follower) is configured with http_port = 8030 (or 8032), FE2 will attempt to reach the Leader at 127.0.0.1:8032.
* Verification: Check the fe.log on the follower. Look for the line immediately preceding the "Connection refused" error. It should print the literal URL it is attempting to hit (e.g., `http://127.0.0.1:8031/api/bootstrap`).
* If the port in that URL is not 8031, you have a port mismatch in your fe.conf.
* In a colocated setup with different loopback IPs, all FEs should ideally use the same http_port (e.g., 8030) to avoid this discovery issue.
3. Environment Proxies
In AWS environments, global proxy settings (like http_proxy or https_proxy in /etc/environment) can interfere. curl often ignores these for loopback or is configured with no_proxy, but the JVM's HttpURLConnection (used by StarRocks) will honor them.
* Action: Run env | grep -i proxy on the box. If proxies are set, add -Dhttp.nonProxyHosts="127.0.0.1|localhost|127.0.0.*" to your JAVA_OPTS in fe.conf.
4. Why 9363239?
This number is almost certainly the Last Checkpoint ID.
1. The follower starts and wipes metadata.
2. It connects to the leader via the BDB-JE port (9011) successfully (this is why SHOW FRONTENDS shows it as Alive).
3. The leader tells the follower: "You are too far behind, download image 9363239."
4. The follower might have successfully downloaded that image once (or it's cached), but now it's trying to get the next piece of data via an HTTP call to the leader's /api/bootstrap or /journal endpoint.
5. The HTTP call fails with Connection refused, and the replayer thread (or the main thread waiting on it) hangs, leaving the ReplayedJournalId at the image's base version.
Summary Checklist:
1. Match Ports: Ensure http_port is identical across all FEs if possible, or verify the follower is actually trying to hit 8031.
2. IPv4 Stack: Force -Djava.net.preferIPv4Stack=true.
3. Check URLs: Find the literal failed to get result from url: http://... line in fe.log to see the exact IP and Port the JVM is targeting.
4. Priority Networks: Ensure priority_networks = 127.0.0.x/32 is set correctly for each FE so they don't try to use the AWS internal eth0 IP to talk to a loopback listener.
References
• administration/Meta_recovery.mdRohit
09/08/2026, 7:32 AM-<http://Djava.net|Djava.net>.preferIPv4Stack=true -<http://Djava.net|Djava.net>.preferIPv6Addresses=false, did a full clean rejoin (wipe meta, drop/re-add follower, fresh start), identical failure again.
Full list of what's been ruled out across 4 clean wipe-and-rejoin attempts, all with the identical Connection refused on the helper HTTP call:
• External catalogs (none configured)
• Leader IP/advertisement (SHOW PROC '/frontends' shows correct 127.0.0.1)
• Leader reachability (curl -v <http://127.0.0.1:8031/> succeeds instantly, returns expected 401)
• IPv4/IPv6 stack preference
• Proxy env vars (none set)
• Port mismatch (follower's own http_port=8032 isn't what's being called — it's calling the leader's 8031)
• Stale processes/PID files
• File permissions (found and fixed a separate log4j permission issue, didn't affect this)
• Memory/GC pressure (GC logs clean)Rocky
09/08/2026, 7:33 AM--helper <leader_ip>:<edit_log_port>, it successfully establishes a BDB-JE connection (which is why you see Alive: true and a new identity on the leader). However, the follower then needs to call the leader's HTTP API to verify the ClusterId and download metadata images.
The Bug: In StarRocks 3.x, during the initial startup phase (getFeNodeTypeAndNameFromHelpers), the follower guesses the leader's HTTP port based on its own fe.conf.
* If FE1 (Leader) is on 8031 and FE2 (Follower) is on 8032, FE2 will attempt to reach the leader at 127.0.0.1:8032.
* Because the leader is only listening on 8031, the JVM returns Connection refused.
* Your curl worked because you manually targeted 8031.
Why the jstack shows it stuck: The main thread is caught in a retry loop because it cannot complete the HTTP-based verification. Because it can't verify the leader, it never starts the replayer thread, which is why the journal ID never moves.
2. Significance of 9363239
This ID is likely the Checkpoint Image ID currently held in the leader's memory.
* When a follower joins, it replays the incremental BDB-JE logs the leader has available.
* The leader has likely purged logs older than 9363239 (retaining only the latest checkpoint + recent logs).
* The follower reaches the end of the available BDB-JE logs at 9363239 and realizes it must download a full Image to proceed.
* This image download triggers another HTTP call to the leader. This call fails (due to the port mismatch or IPv6/IPv4 binding issue), causing the follower to freeze at that exact ID.
3. The "Stale Identity" and Cluster Reform
Wiping meta_dir is sufficient to clear local state, but the Leader still remembers the old FE identities (IP + Port + Name). If the leader was "reformed" from a dormant state, it may have a token or cluster_id in its VERSION file that the follower is failing to validate during the HTTP call.
Recommended Solution
To resolve the loopback port-discovery bug and the replay freeze:
1. Standardize HTTP Ports (Preferred):
Instead of using different ports on 127.0.0.1, use different loopback aliases. This allows every FE to use the default port 8030, which eliminates the "guessing" error.
* FE1: priority_networks=127.0.0.1/32, http_port=8030
* FE2: priority_networks=127.0.0.2/32, http_port=8030
* FE3: priority_networks=127.0.0.3/32, http_port=8030
2. Force IPv4 on the Listener:
Ensure the Leader is explicitly listening on the IPv4 loopback. In fe.conf, ensure:
properties
JAVA_OPTS="-Djava.net.preferIPv4Stack=true"
And check netstat -plnt | grep 8031 to ensure it says 127.0.0.1:8031 and not :::8031.
3. Clean Rejoin Sequence:
Because the leader may have stale journal info for 9363239, do this exact sequence:
1. Leader: ALTER SYSTEM DROP FOLLOWER "127.0.0.x:9011"; (Drop the stuck one).
2. Follower: rm -rf fe/meta/*
3. Leader: ALTER SYSTEM ADD FOLLOWER "127.0.0.x:9011";
4. Follower: Start with --helper <leader_ip>:9011.
4. Check for "Token" Mismatch:
If the error persists, check the leader's fe/meta/image/VERSION. Note the token. Manually try to curl the bootstrap API with that token from the follower:
curl -v "<http://127.0.0.1:8031/api/bootstrap?cluster_id=...&token=...>"
If this returns anything other than a JSON success, the leader's internal web server is rejecting the follower's credentials.
ReferencesRocky
09/08/2026, 7:33 AMRohit
09/08/2026, 7:35 AM/api/bootstrap endpoint reports "replayedJournalId":9363239" — but the actual latest checkpoint image on disk is image.9513240 (generated today at 07:20, current and valid). These numbers don't match; the bootstrap endpoint appears to be serving a stale/cached value that doesn't reflect the leader's real current state.
Every follower join attempt has been told to sync to 9363239 (the stale value) rather than the real, current 9513240 image — which would explain the consistent freeze at that exact number across every rejoin attempt today.
Question: is this a known caching issue in the bootstrap endpoint (e.g., an in-memory field that's only refreshed on certain triggers, not on every checkpoint), and would restarting the leader FE (FE1) safely force it to pick up the current image reference? Since FE1 is our live production leader, we want to confirm this is the right and safe fix before restarting it — is there a way to force-refresh this without a restart, or should we plan a brief, careful leader restart?Rocky
09/08/2026, 7:36 AMimage.9513240) and the leader's API ("replayedJournalId": 9363239) is a known edge case where the Leader's in-memory metadata pointer for the bootstrap handshake has become decoupled from the actual state of the journal and checkpoint system.
1. Is this a known caching issue?
Yes. In certain StarRocks 3.x versions, the GlobalStateMgr (formerly Catalog) maintains a high-water mark for the journal ID that is used to respond to joining followers. While the Checkpoint Daemon correctly writes the new image to disk and purges old logs, a specific race condition or exception during the "image-to-journal" transition can occasionally prevent the Leader from updating the specific volatile field used by the /api/bootstrap endpoint.
Because the Leader has already purged BDB-JE logs older than 9513240 (having successfully checkpointed them), any follower told to sync to 9363239 will immediately find that those logs no longer exist. This triggers a loop where the follower asks for logs the leader has already deleted, resulting in the "stuck" state you are seeing.
2. Can you refresh this without a restart?
No. There is currently no ADMIN command or HTTP endpoint to force-refresh the internal replayedJournalId field used by the bootstrap process. This value is initialized during the Leader's startup and updated as logs are committed; once it falls behind the "purge" point of the BDB-JE logs, the only way to re-align the Leader's in-memory state with the disk is a restart.
3. Safety of restarting the Leader (FE1)
Since FE2 and FE3 are not currently joined, restarting FE1 will result in temporary downtime for the cluster (no metadata service or query handling) for the duration of the restart (usually 30–90 seconds).
Procedure for a safe recovery:
1. Backup: Ensure you have a copy of the fe/meta directory of FE1 (the leader) as a safety measure.
2. Restart FE1:
* Stop FE1: ./bin/stop_fe.sh
* Wait for the process to fully exit.
* Start FE1: ./bin/start_fe.sh --daemon
* Monitor fe.log until you see Finished to start FE.
3. Verify API: Immediately check curl <http://127.0.0.1:8031/api/bootstrap>. It should now correctly report a replayedJournalId $\ge$ 9513240.
4. Join Followers:
* Ensure the follower meta_dir is clean.
* Start FE2: ./bin/start_fe.sh --helper 127.0.0.1:9011 --daemon
* The follower should now successfully download the correct image (9513240) and proceed to replay incremental logs.
Summary
The Leader restart is the only way to clear this specific metadata "hang." Once FE1 reloads from its own image.9513240, the bootstrap API will serve the correct ID, allowing your followers to finally bypass the 9363239 roadblock.
References
• faq/operation_maintenance_faq.md
• administration/management/FE_configuration.md
• administration/Meta_recovery.md
• administration/user_privs/authorization/ranger_plugin.md
• faq/Deploy_faq.mdRohit
09/08/2026, 8:04 AMreplayedJournalId, and both FE2 and FE3 successfully joined without the previous "not added to group" loop or connection-refused errors.
But a new/related problem: both followers get the leader's image at join time (9521646) and then immediately freeze there — they never advance past that point, even though the leader continues climbing normally (currently ~9524000+, gap growing). Confirmed via repeated checks 15-60 seconds apart — followers show zero movement in ReplayedJournalId while the leader moves forward by dozens to hundreds of entries in the same window.
So the pattern is: followers can now sync the initial image successfully (that part is fixed), but incremental journal replay after the initial image never starts — same symptom as before, just no longer blocked by the stale bootstrap value.
Questions:
1. Is there a separate mechanism/thread responsible for switching a follower from "loaded initial image" to "replaying live incremental journal," and could that be failing to start even though the image transfer itself succeeds?
2. Given this is a shared_nothing colocated setup with all 3 BEs on 127.0.0.1 (different ports) — could tablet/replica report entries in the incremental journal be causing the replayer to silently stall when applied against this non-standard BE topology, even though the initial image load doesn't hit that code path?
3. Is there a specific log line/thread name (beyond what we've checked — stateChangeExecutor, globalStateMgr, replay) that indicates whether the incremental replay thread pool even started for a follower, so we can confirm whether it's stalled vs. never launched?Rocky
09/08/2026, 8:05 AMReplayedJournalId is named replayer.
* How it starts: After the main thread finishes loadImage, it kicks off the replayer daemon thread. This thread runs a loop: JournalCursor.next() $\rightarrow$ applyJournalEntry().
* The Log Signal: Check fe.log on the follower for:
text
replayer thread catch an exception when replay journal <ID>
If you see this, the replayer is crashing and restarting on the same entry. If you see nothing, the thread is likely Blocked or Waiting.
* Verification: Run jstack <pid> | grep -A 20 '"replayer"'.
* If it’s in BDBJournalCursor.next(), the follower is waiting for BDB-JE to deliver the next log from the leader.
* If it’s in any Catalog.save... or apply... method, it is stuck trying to execute the logic of a specific metadata change.
2. The "Colocated Loopback" Trap (BDB-JE level)
While HTTP and curl work, BDB-JE (the library StarRocks uses for journaling) has its own internal handshake. In a colocated setup on 127.0.0.1, BDB-JE can get confused if the Node Name or Identity doesn't match the IP/Port exactly as the leader expects.
* Internal BDB-JE Threads: Look in your jstack for threads named like Replica <IP>_<Port>.... If these threads are missing or in a TERMINATED state, the background BDB replication has failed.
* The "Double Identity" Bug: Check the leader's fe.log for "is already active with the Feeder: null". This happens if a follower tries to rejoin, but the leader still holds an "orphaned" BDB-JE socket for that same IP/Port. Because the loopback is shared, BDB-JE might reject the "new" connection from the "old" identity.
* Fix: Ensure each FE has a unique name (the name in fe/conf/fe.conf isn't used for this; StarRocks uses the IP_Port combination). In your setup, ensure priority_networks is explicitly set to 127.0.0.1/32 on all nodes to prevent BDB from picking up a local eth0 IP.
3. Tablet/Replica Report Stalls
You asked if tablet reports could stall the replayer. Yes.
* When a BE (even on 127.0.0.1) reports its tablets, the leader writes a BACKEND_TABLETS_INFO or similar entry to the journal.
* If the follower replaying this entry tries to perform a synchronous DNS lookup or a reverse IP lookup on that BE's address (127.0.0.1) and the OS's nsswitch.conf or /etc/hosts is misconfigured, the replayer thread will hang for the duration of the TCP/DNS timeout.
* Diagnostic: Check if jstack shows the replayer thread inside a <http://java.net|java.net> or InetAddress call.
Recommended Action Plan
1. Inspect the replayer thread state:
bash
# Run this on the follower
jstack <pid> | grep -A 30 "replayer"
If it's stuck in Object.wait(), it's waiting for BDB-JE. If it's stuck in SocketInputStream.read(), it's a network/BDB hang.
2. Verify BDB-JE Log Levels:
Add this to your follower's fe.conf to see exactly why the incremental logs aren't arriving:
properties
bdbje_log_level = FINE
(Requires a restart). This will flood fe.log with the internal BDB-JE heartbeat and handshake details.
3. Check for "Version" file mismatch:
Compare fe/meta/image/VERSION on the leader vs. the follower. Ensure the clusterId and token are identical. If the image download was successful, they should match, but if they don't, BDB-JE will refuse to stream logs.
4. Confirm the Leader sees the Follower as "Replicating":
On the leader, run:
```sqlRocky
09/08/2026, 8:05 AMAlive, but its ReplayedJournalId in this output is also static, the leader's Feeder thread (the one that pushes logs) might be the one stuck. Check the leader's jstack for a thread named Feeder <Follower_IP>.
References
• administration/Meta_recovery.mdRohit
09/08/2026, 8:24 AMmeta_dir, dropped both from the leader, started FE2 and FE3 together back-to-back, added both back as followers. Identical result as every previous attempt.
jstack on the fresh follower process confirms: main thread stuck in NodeMgr.getClusterIdAndRoleOnStartup() → getFeNodeTypeAndNameFromHelpers(), still logging "not added to the group... Connection refused" against 127.0.0.1:9011 even 5+ minutes after start, with ALTER SYSTEM ADD FOLLOWER already issued.
This rules out leftover/stale state as the cause — it's now reproduced identically across 5+ separate attempts today, including one fully clean simultaneous restart of both followers from scratch.
What's confirmed working on the leader side:
• HTTP port 8031 reachable via curl
• /api/bootstrap returns correct current data (fixed via leader restart earlier today)
• Feeder/replication manager threads (FeederManager.runFeeders) are running
• VERSION file token/clusterId match between leader and followers
• ALTER SYSTEM ADD FOLLOWER succeeds, leader's SHOW FRONTENDS shows the follower registered
What's still failing:
• The follower's own JVM never completes the join handshake — its internal HttpURLConnection call to the helper keeps returning Connection refused, despite the same host:port being reachable via curl at the OS levelRocky
09/08/2026, 8:24 AMConnection refused error against 127.0.0.1:9011 (the edit_log_port), combined with your jstack results, points to a specific architectural limitation in how StarRocks handles initial handshakes in a colocated setup (multiple FEs on the same IP).
1. The "Helper Port" Confusion
When you start a follower with --helper 127.0.0.1:9011, the StarRocks code in getFeNodeTypeAndNameFromHelpers takes that port and uses it for two different things:
1. BDB-JE Handshake: It correctly uses 9011 to establish the metadata replication stream.
2. HTTP Handshake (The Bug): In many StarRocks versions (including 3.x), the follower attempts to call the helper's HTTP API (to check node type and name) before it fully joins the group. Because it doesn't know the leader's http_port yet, it often falls back to using the port provided in the helper string as the HTTP port.
Since 9011 is a TCP socket for BDB-JE and not an HTTP server, the JVM receives a connection rejection or a protocol mismatch, leading to the Connection refused or "not added to group" loop you are seeing.
2. The "Same Port" Assumption
StarRocks internally assumes that all FE nodes in a cluster use the same port configuration.
* If your follower has http_port=8032, it may try to reach the leader at 127.0.0.1:8032.
* If that fails, it tries the --helper port (9011).
* Both are wrong, because your leader is listening on 8031.
The Recommended Fix: IP Aliasing
To resolve this without fighting the internal port-discovery logic, you should move away from using different ports on 127.0.0.1. Instead, give each FE its own loopback IP. This allows every node to use the default ports, which eliminates the discovery ambiguity.
Step 1: Create IP Aliases
Run these on your host (Linux example):
bash
sudo ip addr add 127.0.0.2 dev lo
sudo ip addr add 127.0.0.3 dev lo
Step 2: Reconfigure FEs to use standard ports
Update your fe.conf files so all nodes use the same ports but different IPs:
* FE1 (Leader): priority_networks=127.0.0.1/32, http_port=8030, edit_log_port=9010
* FE2 (Follower): priority_networks=127.0.0.2/32, http_port=8030, edit_log_port=9010
* FE3 (Follower): priority_networks=127.0.0.3/32, http_port=8030, edit_log_port=9010
Step 3: Clean Rejoin
1. Leader: ALTER SYSTEM DROP FOLLOWER "127.0.0.2:9010"; (and .3)
2. Follower: rm -rf fe/meta/*
3. Leader: ALTER SYSTEM ADD FOLLOWER "127.0.0.2:9010";
4. Follower: ./bin/start_fe.sh --helper 127.0.0.1:9010 --daemon
Why this fixes the freeze
1. Handshake: When the follower starts, it will try to reach 127.0.0.1:8030 (default) for the HTTP check. Since the leader is now on 8030, the check succeeds immediately.
2. Replayer: The "freeze" you saw earlier after the image sync was likely caused by the BDB-JE replayer thread getting confused by the mismatching ports in the BDB group metadata. By standardizing the ports and using distinct IPs, BDB-JE can cleanly distinguish the nodes without port-mapping conflicts.
Summary of what went wrong
Your clean wipe reset the followers to the "Initial Join" phase, which triggered the getFeNodeTypeAndNameFromHelpers check. This check is failing specifically because of your non-standard port layout on a shared IP. Using IP aliases is the standard community workaround for running a full StarRocks cluster on a single machine.
References
• administration/management/FE_configuration.mdRohit
09/08/2026, 9:34 AM127.0.0.2, 127.0.0.3) matching ports (http_port=8031, edit_log_port=9011, same as the leader), full clean wipe and rejoin. Identical freeze again, same exact number as every prior attempt: 9521646.
This rules out the port/IP-ambiguity theory — the fix was applied correctly and didn't change the outcome.
New observation, possibly the real lead: 9521646 has been the exact same freeze value across every single attempt since yesterday — including today's, which used a completely different network config. The leader was restarted yesterday at 07:53:09 (to fix the earlier stale-bootstrap-value bug), and 9521646 appears to correspond to the image generated shortly after that restart. Every follower join since then, regardless of method, syncs to that same image and then stalls — while the leader's own live ReplayedJournalId has continued climbing normally (now well past 9.54M).
This raises a real question: has the leader actually generated a new checkpoint image since yesterday's restart, or is 9521646 still the most recent image on disk?
Checking now via ls -la /data/starrocks/fe1/meta/image/v2/ — if the leader hasn't produced a newer checkpoint despite the journal advancing by tens of thousands of entries, that would point to the leader's own checkpoint daemon being stalled or broken, not a follower networking/config issue at all. That would explain why every follower-side fix (port config, IP aliasing, IPv4 forcing, sequential vs. simultaneous join) produces the identical symptom — they're all correctly waiting for a next checkpoint that the leader simply isn't producing.
Questions:
1. What StarRocks internal process/thread is responsible for generating periodic checkpoint images on the leader (separate from the live journal replay), and what config controls its interval?
2. If that process has stalled, what's the typical cause — and is there a way to check its last-run status or force a manual checkpoint?
3. Given the leader's own live replay is healthy (journal climbing fine) but checkpoint generation may be stalled, would this explain followers getting stuck exactly here regardless of their own configuration?Rocky
09/08/2026, 9:35 AM9521646 across different network configurations and clean wipes is a very strong signal. It confirms that the followers are successfully completing the "Image Download" phase but are failing to transition into the "Journal Replay" phase.
To answer your specific questions about the leader's checkpointing:
1. The Checkpoint Process and Thread
On the Leader FE, the internal thread responsible for metadata checkpoints is the Checkpointer (in some versions, orchestrated by the CheckpointController).
* Mechanism: It doesn't run on a fixed timer (like every hour). Instead, it is triggered by the Journal Count.
* Trigger Configuration: The primary control is edit_log_roll_num, which defaults to 50,000.
* The Logic: A new checkpoint (and thus a new image.xxxx file) is only generated once the number of new journal entries since the last image exceeds this threshold.
2. Is the Leader's Checkpoint Daemon Stalled?
Given your observation:
* Last Image: 9521646
* Leader Current Journal: ~9,540,000
* Current Gap: ~18,354 entries.
Conclusion: The Leader's checkpoint daemon is likely *not stalled*; it simply hasn't reached the 50,000-entry threshold required to trigger a new image. It is normal for the leader to stay on the same image file for a long time if the journal volume hasn't hit the limit.
3. Why the Followers are Stuck at the Image ID
A follower should not wait for a new checkpoint to join. The normal lifecycle is:
1. Load image.9521646.
2. Connect to the Leader's BDB-JE service (port 9011).
3. Stream and replay journals 9521647 through 9,540,000+.
The "freeze" happens because the followers are failing at Step 2 or 3. Your jstack find is the smoking gun:
The Bug: In StarRocks, during this specific handshake, the follower attempts an HTTP call to the helper. If it doesn't know the leader's HTTP port yet, it often mistakenly tries to use thethread stuck inmain->NodeMgr.getClusterIdAndRoleOnStartup()...getFeNodeTypeAndNameFromHelpers()againstConnection refused.127.0.0.1:9011
--helper port (9011) for the HTTP request. Since 9011 is a BDB-JE socket, not an web server, the connection is refused.
How to Force a Manual Checkpoint
If you want to verify the leader can still create images (to rule out a stall), you can force it by temporarily lowering the threshold:
1. Lower the threshold:
sql
ADMIN SET FRONTEND CONFIG ("edit_log_roll_num" = "100");
2. Wait 1-2 minutes: The Checkpointer thread should notice the current gap (~18k) exceeds 100 and will trigger a new image.
3. Check disk: ls -la /data/starrocks/fe1/meta/image/v2/. You should see a new image.954xxxx file.
4. Restore the default:
sql
ADMIN SET FRONTEND CONFIG ("edit_log_roll_num" = "50000");
Why IP Aliasing didn't fix the "Connection Refused"
If you provided --helper 127.0.0.1:9011, the follower is still trying to talk to the Leader's BDB port via HTTP.
The Solution: In your fe.conf for the followers, you must ensure that http_port and edit_log_port match the Leader's ports, and your --helper flag should point to the leader's BDB port.
However, if the handshake is still failing, it usually means the Leader has already designated these followers as "DEAD" or "REPLICA" in a way that blocks the new handshake.
1. Drop them again: ALTER SYSTEM DROP FOLLOWER "127.0.0.2:9011";
2. Ensure Helper is Correct: Start the follower using the Leader's IP and BDB Port:
./bin/start_fe.sh --helper 127.0.0.1:9011 --daemon
3. Check Leader Logs: Look for "rejecting connection from..." or "node name mismatch".Rocky
09/08/2026, 9:35 AMADMIN command above to prove the leader is fine, then focus on why the follower's main thread is failing the getFeNodeTypeAndNameFromHelpers call.
References
• administration/management/FE_configuration.md
• administration/Meta_recovery.md
• administration/management/monitoring/Monitor_and_Alert.md
• administration/management/monitoring/metrics.md
References
• administration/management/FE_configuration.md
• administration/management/monitoring/metrics.md
• administration/management/monitoring/Monitor_and_Alert.md
• administration/management/BE_configuration.mdRohit
09/08/2026, 10:41 AM127.0.0.1
• FE2: 127.0.0.2
• FE3: 127.0.0.3
All FEs currently use:
• http_port = 8031
• edit_log_port = 9011
Each FE has its own `priority_networks`:
• FE1: 127.0.0.1/32
• FE2: 127.0.0.2/32
• FE3: 127.0.0.3/32
FE1 is healthy production leader and must not be restarted or modified.
The issue is that FE2/FE3 cannot start. FE2 eventually logs:
edit_log_port 9011 is already in use. will exit.
And ss on the server shows FE1 is actually listening as:
*:9011
*:9021
*:9031
rather than binding specifically to 127.0.0.1.
My question is:
Does StarRocks support running multiple FE instances on the same Linux host using different loopback IPs with the same `edit_log_port`/`http_port`, relying on priority_networks to distinguish the bindings?
If yes, why would FE1 bind to *:9011 despite priority_networks = 127.0.0.1/32, and what is the correct way to configure FE2/FE3 without touching FE1?
If no, what is the officially recommended topology/configuration for this scenario?
StarRocks version: 3.5.13-dca7c0a.Rocky
09/08/2026, 10:42 AMpriority_networks parameter is primarily used for self-identification and discovery (deciding which IP to advertise to other nodes in the metadata). It does not automatically force all internal services (BDB-JE, Thrift, Jetty, MySQL NIO) to bind only to that specific IP.
By default, the FE binds its listener sockets to 0.0.0.0 (all interfaces) so that it is accessible via any available IP on the host. When FE1 binds to *:9011 (all interfaces), it "claims" port 9011 for the entire host. Even if you have 127.0.0.2 available, any attempt by FE2 to bind to 127.0.0.2:9011 will fail because 0.0.0.0:9011 already covers that address.
2. Can you fix this without touching FE1?
No. As long as FE1 is listening on *:9011, no other process on that same Linux VM can bind to port 9011 on any IP address (loopback or otherwise). To allow FE2 and FE3 to use port 9011 on their respective IPs, FE1 must be reconfigured to bind specifically to 127.0.0.1:9011.
3. Recommended Solution (The "No-Restart" Conflict)
Since you cannot restart or modify FE1, you are physically blocked from using port 9011 for any other FE on this VM. You have two options:
Option A: Use Different Ports (Recommended for your constraint)
Since you cannot modify FE1, you must assign unique ports to FE2 and FE3. This is the standard way to run multiple StarRocks components on a single host.
* FE1: http_port=8031, edit_log_port=9011, query_port=9031, rpc_port=9021
* FE2: http_port=8032, edit_log_port=9012, query_port=9032, rpc_port=9022
* FE3: http_port=8033, edit_log_port=9013, query_port=9033, rpc_port=9023
Option B: Bind to Specific IPs (Requires FE1 Restart)
If you ever gain the window to restart FE1, you can force StarRocks to bind to specific IPs instead of 0.0.0.0 by adding the following to all fe.conf files:
properties
# Add this to force binding to the IP selected by priority_networks
# This is available in newer 3.x versions
frontend_address = 127.0.0.1 (use .2 for FE2, .3 for FE3)
_Note: Ensure priority_networks is also set. If frontend_address isn't supported or effective for all ports in your specific sub-version, the unique port strategy (Option A) is the only foolproof method._
Summary
* Does it support same ports on different IPs? Technically yes, if frontend_address is used to restrict binding.
* *Why did FE1 bind to *?* Default behavior is to listen on all interfaces (0.0.0.0).
* How to fix FE2/FE3 now? Since FE1 is "squatting" on all interfaces for port 9011, you must use different ports for FE2 and FE3 (e.g., 9012, 9013) or accept that FE1 must be modified to "yield" the other IPs.
References
• administration/management/FE_configuration.md
• administration/management/BE_configuration.md
• faq/Deploy_faq.md
• administration/Meta_recovery.mdRohit
09/08/2026, 10:43 AMALTER SYSTEM DROP FOLLOWER for FE2/FE3?
2. Then change their fe.conf ports?
3. Then ALTER SYSTEM ADD FOLLOWER using the new edit_log ports?
4. Then start FE2/FE3 with --helper 127.0.0.1:9011?
5. Is there any risk to the existing FE1 metadata or cluster?
Please provide the exact command sequence for FE2 first, with FE1 left completely untouched.Rocky
09/08/2026, 10:44 AM*) bindings. Following these steps for FE2 first will not affect FE1’s availability or metadata.
Safe Procedure for FE2
1. Cleanup on FE1 (The Leader)
Connect to FE1 using a MySQL client and remove the old, non-functional registration for FE2.
sql
-- Remove the old identity (the one using port 9011)
ALTER SYSTEM DROP FOLLOWER "127.0.0.2:9011";
-- Verify it is gone (Role should only show FE1 as LEADER)
SHOW FRONTENDS;
2. Reconfigure FE2
Modify fe/conf/fe.conf on the FE2 instance. You must change all four primary ports to ensure there is no overlap with FE1’s wildcard listeners.
properties
# fe2/conf/fe.conf
# Network bindings
priority_networks = 127.0.0.2/32
# Unique ports for FE2
http_port = 8032
rpc_port = 9022
query_port = 9032
edit_log_port = 9012
3. Clean local state on FE2
Ensure the metadata directory is completely empty to prevent any "stale node name" or "cluster ID mismatch" errors during the new handshake.
bash
# Run on the FE2 node
rm -rf /path/to/fe2/meta/*
4. Register FE2 with New Ports on FE1
In your MySQL session on FE1, register the new port-specific identity.
sql
-- Register the new identity using the new edit_log_port
ALTER SYSTEM ADD FOLLOWER "127.0.0.2:9012";
5. Start FE2 with Helper
Start the FE2 process. The --helper flag must point to the Leader’s (FE1) current IP and edit_log_port.
bash
# Run on the FE2 node
./bin/start_fe.sh --helper 127.0.0.1:9011 --daemon
6. Verify Join
Check the status on FE1:
sql
SHOW FRONTENDS;
* FE2 should appear with IP: 127.0.0.2 and EditLogPort: 9012.
* Alive should be true.
* Join should be true.
──────────
Risks and Confirmations
* Risk to FE1: There is zero risk to FE1’s metadata. ALTER SYSTEM DROP/ADD commands only update the leader's node registry. FE1 does not need to be restarted.
* Quorum: Since FE2 and FE3 were already down/non-functional, dropping them does not change the quorum status of your cluster; FE1 is already functioning as a single-node "majority."
* Why this works: When FE1 listens on *:9011, it blocks any other process from using 9011. It does not block other processes from using 9012 on any IP. By moving FE2 to 9012, the OS can successfully grant the binding.
* FE3: Once FE2 is successfully joined and Alive, repeat the same steps for FE3 using ports 8033, 9023, 9033, 9013 and the IP 127.0.0.3.
Summary of Helper Logic
The --helper parameter is only used for the very first start of a clean node. It tells the new node where to find the leader to download the initial metadata image. Once the node has joined, it stores the cluster info in its local meta/ directory and will not need the --helper flag for future restarts.
References
• deployment/deploy_manually.md
• administration/Meta_recovery.mdRohit
09/08/2026, 12:15 PMcurl succeed instantly against the leader's HTTP port, while the follower's own JVM (HttpURLConnection, inside NodeMgr.getFeNodeTypeAndNameFromHelpers()) gets Connection refused on the identical host:port, at the same moment, from the same machine?
This isn't a reachability problem — curl proves the port is open and answering. So the JVM's connection attempt must be failing before or differently than curl's:
• Is there a JVM-level connection timeout/pool setting in this call path that could produce Connection refused instead of a timeout, even when the target is reachable (e.g., a source-port exhaustion, an ephemeral port binding conflict, a security manager restriction from udf_security.policy)?
• Could StarRocks' own HTTP client be binding to a specific local interface/port before connecting, and something about that specific bind is failing, distinct from curl's default behavior?
• Is there a way to get more detail than ConnectException: Connection refused from this specific call — e.g., enabling verbose Java networking debug (-<http://Djavax.net|Djavax.net>.debug=all or similar) to see exactly what's happening at the socket level?
We're not looking for another config to try — we've exhausted the standard list. We need to understand the actual mechanism causing this specific JVM-vs-curl discrepancy, since that's the only thing that hasn't been directly explained yet.Rocky
09/08/2026, 12:15 PMcurl and the StarRocks JVM is the "smoking gun" for your issue. The reason curl succeeds while the JVM fails with Connection refused is almost certainly a port mismatch in the follower's internal discovery logic, rather than a networking/reachability problem.
1. The Mechanism: Why the JVM is failing
In the StarRocks FE startup sequence, specifically inside NodeMgr.getFeNodeTypeAndNameFromHelpers(), the follower must contact the Leader to verify the cluster identity before it downloads the metadata image.
The problem lies in how the follower determines which port to use for this HTTP call:
* The Follower's Logic: When you provide --helper 127.0.0.1:9011, the follower knows the Leader's edit_log_port is 9011. However, it needs to make an HTTP call. In many versions of StarRocks (and its predecessors), the code assumes that all FEs in the cluster use the same http_port.
* The Conflict:
* You configured FE2 with http_port = 8032.
* When FE2 tries to talk to the Leader (FE1), it uses its own configured port (8032) to build the URL: <http://127.0.0.1:8032/api/bootstrap>.
* FE1 (Leader) is only listening on 8031.
* The OS sees a connection attempt to 127.0.0.1:8032 where nothing is listening, and immediately returns Connection refused.
* Why curl works: When you test with curl, you are likely (and correctly) targeting <http://127.0.0.1:8031>. You are smarter than the follower's bootstrap logic, which is currently "blind" to the leader's actual HTTP port.
2. Is this a known constraint?
Yes. StarRocks official documentation and deployment best practices state that all FE nodes in a cluster must use the same http_port. While the cluster can technically operate with different ports once the metadata is fully synced and stored, the join/bootstrap phase is hardcoded to assume port consistency across the helper list.
3. How to verify (Debugging)
To see exactly what the JVM is doing, you don't need general network debugs (which are very noisy). Instead, use strace to catch the specific connect() system call:
bash
# Run this while starting FE2
strace -f -e trace=connect ./bin/start_fe.sh --helper 127.0.0.1:9011 --daemon
Look for a line like connect(..., {sa_family=AF_INET, sin_port=htons(8032), sin_addr=inet_addr("127.0.0.1")}, ...). This will prove the JVM is targeting the wrong port.
4. The Path Forward
To run multiple FEs on the same host, you have two choices:
1. Uniform Ports (The "Proper" Way): Configure all FEs to use http_port = 8031. To avoid the *:8031 conflict, you must force the Leader (FE1) to bind only to 127.0.0.1. Add frontend_address = 127.0.0.1 to FE1's fe.conf and restart it. This allows FE2 to bind to 127.0.0.2:8031 without conflict.
2. Manual Image Side-loading (The "Hack"): If you absolutely cannot restart FE1, you can try to bypass the helper check by manually copying the Leader's meta/image directory to the Follower's meta directory before starting. However, even if it starts, you will likely encounter further Connection refused errors later when the Leader tries to send heartbeats back to the Follower's (different) RPC ports.
Recommendation: The single-VM, multi-IP, multi-port FE topology is non-standard and fights against StarRocks' internal assumptions. If FE1 must remain untouched, your best bet is to move FE2/FE3 to a different VM or a container where they can use the standard ports (8030, 9010, etc.) without port-mapping conflicts.
References
• administration/management/FE_configuration.md
• faq/Deploy_faq.md
• administration/management/BE_configuration.mdRocky
09/08/2026, 12:15 PMRohit
09/08/2026, 12:22 PMRocky
09/08/2026, 12:22 PM*:9011 (all interfaces), it physically blocks FE2 and FE3 from using that port on their own IPs. You must add frontend_address = 127.0.0.1 to FE1’s config.
Table 1: Frontend (FE) Configuration
Node | IP | http_port | edit_log_port | query_port | rpc_port
FE1 | 127.0.0.1 | 8030 | 9010 | 9030 | 9020
FE2 | 127.0.0.2 | 8030 | 9010 | 9030 | 9020
FE3 | 127.0.0.3 | 8030 | 9010 | 9030 | 9020
Table 2: Backend (BE) Configuration
Node | IP | heartbeat_port | be_port | http_port | brpc_port
BE1 | 127.0.0.4 | 9050 | 9060 | 8040 | 8060
BE2 | 127.0.0.5 | 9050 | 9060 | 8040 | 8060
BE3 | 127.0.0.6 | 9050 | 9060 | 8040 | 8060
──────────
The Literal Configuration Settings
To ensure the JVMs do not conflict, you must include these specific lines in every config file:
For FEs (fe.conf)
properties
# Match the IP from the table for each node
priority_networks = 127.0.0.X/32
# Forces StarRocks to bind ONLY to this IP, freeing up the port for other IPs
frontend_address = 127.0.0.X
For BEs (be.conf)
properties
# Match the IP from the table for each node
priority_networks = 127.0.0.X/32
# Forces BE to bind to the specific loopback IP
be_ip = 127.0.0.X
Why this is the only way it works:
1. Uniform Ports: StarRocks' internal bootstrap logic (the helper handshake) expects all FEs to share the same HTTP/RPC ports. If FE1 is on 8031 and FE2 is on 8032, the join will fail with Connection refused because the follower tries to guess the leader's port based on its own config.
2. Explicit Binding: By using frontend_address and be_ip, you stop the "wildcard" binding (*:9010). This allows the Linux kernel to let FE1 use 127.0.0.1:9010 while FE2 simultaneously uses 127.0.0.2:9010.
If you cannot touch FE1, you are effectively prevented from adding any other FE to this VM using the same port, and you will continue to hit the "JVM vs. curl" port-mismatch logic if you use different ports. To proceed, you must allow FE1 to be reconfigured with the frontend_address property.Rohit
09/08/2026, 12:26 PM127.0.0.4/5/6).
Our BEs are currently all on shared 127.0.0.1, differentiated only by port — and they're working completely fine. SHOW BACKENDS shows all 3 alive, healthy, actively serving queries and reporting tablets normally:
BackendId 11165 | 127.0.0.1 | HeartbeatPort 9051 | BePort 9061 | HttpPort 8040 | BrpcPort 8041 | Alive: true
BackendId 17272 | 127.0.0.1 | HeartbeatPort 9052 | BePort 9062 | HttpPort 8051 | BrpcPort 8059 | Alive: true
BackendId 17273 | 127.0.0.1 | HeartbeatPort 9053 | BePort 9063 | HttpPort 8042 | BrpcPort 8043 | Alive: true
This is the exact same "shared IP, different ports" pattern that broke FE follower joins — but it's working fine for BEs. Given that, do we actually need to move the BEs to unique IPs too, or is the port-mismatch issue specific to the FE join/bootstrap code path (NodeMgr.getFeNodeTypeAndNameFromHelpers) and not something BEs hit at all?Rocky
09/08/2026, 12:26 PMALTER SYSTEM ADD BACKEND "127.0.0.1:9051", you are explicitly telling the Leader FE the exact IP and port to use. The FE stores this in its metadata and never has to "guess" another port.
2. No Bootstrap "Blindness": Unlike a new FE Follower, which has to reach out to a Leader it doesn't know yet (and guesses the HTTP port based on its own config), BEs are passive during registration. They wait for the Leader FE to contact them via the heartbeat_service_port you manually registered.
3. Port-Aware Planning: When StarRocks executes a query, the Leader FE creates a plan that includes the specific brpc_port and be_port for each backend involved. BEs simply follow the addresses provided in the query plan.
Summary of the Difference
Component | Port Discovery Mechanism | Shared IP + Different Ports
FE Follower | Hardcoded Guessing: Tries to find the Leader's HTTP port by looking at its own local http_port config. | Fails (if ports aren't uniform)
BE | Explicit Metadata: FE tracks each BE's unique ports (brpc, heartbeat, etc.) as defined in ADD BACKEND. | Works
Recommendation
Since your BEs are already healthy (Alive: true) and serving queries, leave them exactly as they are.
Changing the BEs to unique IPs now would require you to DROP and ADD them again, which would trigger massive data migration/re-balancing as the cluster treats the "new" IPs as entirely new nodes.
The "Unique IP" requirement is specifically to solve the FE bootstrap logic and the `:9010` wildcard binding conflict on the FE side.* Keep your BEs on 127.0.0.1 with their current unique ports and only apply the unique IP strategy to the FEs.
References
• administration/management/BE_configuration.md
• deployment/environment_configurations.md
• administration/management/FE_configuration.md
• deployment/deploy_manually.mdRohit
09/09/2026, 1:38 PMss -tlnp, only the leader shows up listening (wildcard *:<port>), followers had zero open sockets even on their own configured ports.
2. Root cause: the follower's bootstrap handshake incorrectly assumes the leader's HTTP port is the same as its own configured port, rather than using the leader's actual port — so it always calls the wrong address and fails.
3. Even if ports were matched to work around that, StarRocks does a full wildcard bind (not IP-specific), so only one FE can hold a given port per host anyway — blocking multi-FE-per-host regardless.
4. Their conclusion: not fixable via config today, and not something they plan to fix, since multi-FE-per-host doesn't give real HA benefit in the first place (shared failure domain, resource contention).
Does this match your understanding too? Want to confirm before we commit to the "move FE2/FE3 to separate hosts" plan as the resolution.Rocky
09/09/2026, 1:38 PMNodeMgr) is "blind" to the Leader's HTTP port.
* If you use different ports (e.g., Leader: 8030, Follower: 8031): The Follower's JVM tries to contact the Leader on 8031 because it assumes the cluster is uniform. This results in the Connection refused you saw.
* If you use the same port (e.g., both on 8030): The Linux kernel will block the second FE from starting because the first FE has already performed a wildcard bind (0.0.0.0:8030), claiming the port for all IP addresses on that VM.
2. Why BEs are different
Your observation that BEs work fine on shared IPs with different ports is also correct. BEs are registered explicitly by the user (via ADD BACKEND "IP:PORT"). Because you manually tell the Leader exactly which port to use for each BE, the Leader never has to "guess," and the bootstrap blindness never happens. FEs, however, must "discover" the cluster identity before they are fully registered, which is where the guessing logic fails.
3. The "No HA" Reality
The contributor is right on the architectural principle: 3 FEs on one VM provides zero high availability.
* If the VM's NIC fails, the cluster is gone.
* If the VM's disk fills up, all 3 FEs fail.
* If the OS kernel panics, the cluster is gone.
* The FEs will compete for the same CPU/Memory resources, likely leading to JVM GC pauses that could cause the cluster to self-destruct under load.
Final Recommendation
The "move FE2/FE3 to separate hosts" plan is the only way to resolve this.
If you absolutely must keep them on one physical machine for testing/dev purposes, your only alternative is Docker/Containerization. By putting each FE in a container, each one gets its own virtualized network stack and its own "perceived" IP, allowing them all to use the same port (8030) internally without ever seeing each other's port bindings.
But for any environment where data safety matters: Separate hosts are the standard and supported path.
References
• administration/management/FE_configuration.md
• faq/Deploy_faq.md
• administration/management/BE_configuration.md
• administration/management/enable_fqdn.md