XTLS/Xray-core · error

BurstObservatory requires a valid pingConfig

Error message

BurstObservatory requires a valid pingConfig

What it means

Thrown by BurstObservatoryConfig.Build when the burst observatory block has no pingConfig (JSON key pingConfig, Go field HealthCheck). The burst observatory performs concurrent health checks whose parameters (URL, interval, connectivity check, sampling) all live in pingConfig; without it there is nothing to drive health measurement, so build fails. Note the health check settings builder's own errors are propagated unwrapped when pingConfig exists but is invalid.

Source

Thrown at infra/conf/observatory.go:31

	SubjectSelector   []string          `json:"subjectSelector"`
	ProbeURL          string            `json:"probeURL"`
	ProbeInterval     duration.Duration `json:"probeInterval"`
	EnableConcurrency bool              `json:"enableConcurrency"`
}

func (o *ObservatoryConfig) Build() (proto.Message, error) {
	return &observatory.Config{SubjectSelector: o.SubjectSelector, ProbeUrl: o.ProbeURL, ProbeInterval: int64(o.ProbeInterval), EnableConcurrency: o.EnableConcurrency}, nil
}

type BurstObservatoryConfig struct {
	SubjectSelector []string `json:"subjectSelector"`
	// health check settings
	HealthCheck *healthCheckSettings `json:"pingConfig,omitempty"`
}

func (b BurstObservatoryConfig) Build() (proto.Message, error) {
	if b.HealthCheck == nil {
		return nil, errors.New("BurstObservatory requires a valid pingConfig")
	}
	if result, err := b.HealthCheck.Build(); err == nil {
		return &burst.Config{SubjectSelector: b.SubjectSelector, PingConfig: result.(*burst.HealthPingConfig)}, nil
	} else {
		return nil, err
	}
}

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Add a pingConfig object to the burst observatory entry (probeURL, interval, connectivityTimeout, sampling, etc.)
  2. If you do not need health-ping-driven decisions, use the regular observatory instead of burst

Example fix

// before
{ "type": "burst", "subjectSelector": ["out"] }
// after
{ "type": "burst", "subjectSelector": ["out"], "pingConfig": { "destination": "https://www.google.com/generate_204", "interval": "1m", "connectivity": "https://www.google.com/generate_204", "timeout": "5s", "sampling": 2 } }
Defensive patterns

Strategy: validation

Validate before calling

if strings.EqualFold(obs.Type, "burst") && obs.PingConfig == nil {
	return errors.New("burst observatory requires pingConfig")
}

Prevention

When it happens

Trigger: Adding an observatory entry of type burst without a pingConfig object, e.g. {"subjectSelector":["out"],"type":"burst"} with no pingConfig key.

Common situations: Converting a plain (non-burst) observatory config to burst and forgetting that burst mandates pingConfig; trimming config to 'required' fields by mistake.

Related errors


AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15). Data as JSON: /api/errors/e634cb70682504c1. Report an issue: GitHub.