XTLS/Xray-core · error

${idKey} not found in JSON context

Error message

${idKey} not found in JSON context

What it means

Returned by JSONConfigLoader.Load when the top-level JSON object does not contain the loader's identity key (idKey, e.g. "protocol" for inbounds/outbounds). The loader first locates the id key to decide which config creator to invoke; its absence means the JSON fragment cannot be typed. This operates on JSON fragments (like an inbound object), not the whole root config.

Source

Thrown at infra/conf/loader.go:64

	id = strings.ToLower(id)
	config, err := v.cache.CreateConfig(id)
	if err != nil {
		return nil, err
	}
	if err := json.Unmarshal(raw, config); err != nil {
		return nil, err
	}
	return config, nil
}

func (v *JSONConfigLoader) Load(raw []byte) (interface{}, string, error) {
	var obj map[string]json.RawMessage
	if err := json.Unmarshal(raw, &obj); err != nil {
		return nil, "", err
	}
	rawID, found := obj[v.idKey]
	if !found {
		return nil, "", errors.New(v.idKey, " not found in JSON context").AtError()
	}
	var id string
	if err := json.Unmarshal(rawID, &id); err != nil {
		return nil, "", err
	}
	rawConfig := json.RawMessage(raw)
	if len(v.configKey) > 0 {
		configValue, found := obj[v.configKey]
		if found {
			rawConfig = configValue
		} else {
			// Default to empty json object.
			rawConfig = json.RawMessage([]byte("{}"))
		}
	}
	config, err := v.LoadWithID([]byte(rawConfig), id)
	if err != nil {
		return nil, id, err

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Ensure the JSON object passed to the loader contains the id key (for inbounds/outbounds: "protocol")
  2. Pass the complete inbound/outbound object, not just its settings sub-object, to the loader

Example fix

// before
Load([]byte(`{ "settings": {} }`))
// after
Load([]byte(`{ "protocol": "freedom", "settings": {} }`))
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the fragment contains the id key before loading
var obj map[string]json.RawMessage
if err := json.Unmarshal(raw, &obj); err != nil {
	return err
}
if _, ok := obj["protocol"]; !ok {
	return errors.New("fragment is missing the protocol key")
}

Prevention

When it happens

Trigger: Feeding JSONConfigLoader a config fragment missing the id key — e.g. an inbound object without a protocol field, or calling loader.Load with the wrong loader whose idKey differs from the JSON's actual keys.

Common situations: Programmatic use of the conf package where callers pass a raw settings object when the loader expects the full inbound/outbound envelope; JSON typos renaming the protocol key (e.g. 'proto').

Related errors


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