From 5cf8a0854050fad259de5c775cda9e62e35853b6 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Fri, 15 May 2026 11:24:50 +0200 Subject: [PATCH] fix: disable balancer fallbackTag for random / roundRobin strategies Xray-core's RandomStrategy and RoundRobinStrategy register a pending dependency on the Observatory feature whenever fallbackTag is non-empty. Since the panel only provisions observatory for leastPing / leastLoad balancers, picking roundRobin with a fallbackTag caused xray to fail boot with "not all dependencies are resolved". Disable the fallback field for the two strategies that cannot resolve it, and strip fallbackTag from the wire balancer as a defensive backstop for users who edit the JSON template directly. --- frontend/src/pages/xray/BalancerFormModal.vue | 15 +++++++++++++-- frontend/src/pages/xray/BalancersTab.vue | 3 ++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/frontend/src/pages/xray/BalancerFormModal.vue b/frontend/src/pages/xray/BalancerFormModal.vue index 47dd2d41..05aabfeb 100644 --- a/frontend/src/pages/xray/BalancerFormModal.vue +++ b/frontend/src/pages/xray/BalancerFormModal.vue @@ -61,6 +61,16 @@ const isValid = computed( () => !tagEmpty.value && !duplicateTag.value && !emptySelector.value, ); +const fallbackSupported = computed( + () => form.strategy === 'leastPing' || form.strategy === 'leastLoad', +); + +watch(() => form.strategy, (next) => { + if (next !== 'leastPing' && next !== 'leastLoad') { + form.fallbackTag = ''; + } +}); + const tagValidateStatus = computed(() => { if (tagEmpty.value) return 'error'; if (duplicateTag.value) return 'warning'; @@ -111,8 +121,9 @@ const okText = computed(() => - - + + {{ tag || `(${t('none')})` }} diff --git a/frontend/src/pages/xray/BalancersTab.vue b/frontend/src/pages/xray/BalancersTab.vue index 0cf5b602..255ed108 100644 --- a/frontend/src/pages/xray/BalancersTab.vue +++ b/frontend/src/pages/xray/BalancersTab.vue @@ -145,10 +145,11 @@ function syncObservatories() { } function buildWireBalancer(form) { + const supportsFallback = form.strategy === 'leastPing' || form.strategy === 'leastLoad'; const out = { tag: form.tag, selector: [...form.selector], - fallbackTag: form.fallbackTag, + fallbackTag: supportsFallback ? form.fallbackTag : '', }; if (form.strategy && form.strategy !== 'random') { out.strategy = { type: form.strategy };