MHSanaei/3x-ui · error

invalid tag (unknown observatory tag)

Error message

invalid tag (unknown observatory tag)

What it means

ServerController.getXrayObservatoryHistoryBucket validates c.Param("tag") via xrayMetricsService.HasObservatoryTag — only tags actually registered from Xray's burst-observatory outbound config are accepted. 'invalid tag' (detail 'unknown observatory tag') means the tag is not among the observed outbound tags, either mistyped or the observatory feature not configured/started.

Source

Thrown at internal/web/controller/server.go:174

	if !slices.Contains(service.XrayMetricKeys, metric) {
		jsonMsg(c, "invalid metric", fmt.Errorf("unknown metric"))
		return
	}
	bucket, ok := parseHistoryBucket(c)
	if !ok {
		return
	}
	jsonObj(c, a.xrayMetricsService.AggregateMetric(metric, bucket, 60), nil)
}

func (a *ServerController) getXrayObservatory(c *gin.Context) {
	jsonObj(c, a.xrayMetricsService.ObservatorySnapshot(), nil)
}

func (a *ServerController) getXrayObservatoryHistoryBucket(c *gin.Context) {
	tag := c.Param("tag")
	if !a.xrayMetricsService.HasObservatoryTag(tag) {
		jsonMsg(c, "invalid tag", fmt.Errorf("unknown observatory tag"))
		return
	}
	bucket, ok := parseHistoryBucket(c)
	if !ok {
		return
	}
	jsonObj(c, a.xrayMetricsService.AggregateObservatory(tag, bucket, 60), nil)
}

func (a *ServerController) getXrayVersion(c *gin.Context) {
	versions, err := a.serverService.GetXrayVersionsCached()
	if err != nil {
		jsonMsg(c, I18nWeb(c, "getVersion"), err)
		return
	}
	jsonObj(c, versions, nil)
}

View on GitHub (pinned to ad32144c42)

Solutions

  1. First fetch GET /panel/api/server/xrayObservatory (ObservatorySnapshot) and use a tag that appears there.
  2. Align the tag with the outbound's tag field in your Xray config exactly (case-sensitive).
  3. If the snapshot is empty, enable/configure the observatory in the panel and restart Xray so tags register.

Example fix

# before
GET /panel/api/server/history/observatory/proxy-1/60   # invalid tag

# after
curl /panel/api/server/xrayObservatory         # see real tags, e.g. "proxy1"
GET /panel/api/server/history/observatory/proxy1/60
Defensive patterns

Strategy: validation

Validate before calling

const snap = await fetch('/panel/api/server/xrayObservatory').then(r => r.json())
const validTags = new Set(Object.keys(snap?.success?.tags ?? snap?.obj?.tags ?? {}))
if (!validTags.has(tag)) throw new Error(`unknown observatory tag ${tag}`)

Prevention

When it happens

Trigger: GET /panel/api/server/history/observatory/:tag/:bucket with a tag that does not match any outbound tag under the observatory config — e.g. 'proxy-1' when the outbound tag is 'proxy1', or any tag when the panel runs no burst observatory.

Common situations: Outbound tag renamed in config without updating dashboards; observatory disabled or Xray not running so no tags are registered; a fresh panel before any observatory data arrives.

Related errors


AI-assisted analysis of MHSanaei/3x-ui@ad32144c42 (2026-08-15). Data as JSON: /api/errors/d9896fcd234156ac. Report an issue: GitHub.