MHSanaei/3x-ui · error

missing required user field %q

Error message

missing required user field %q

What it means

getRequiredUserString in internal/xray/api.go reports a missing key (or explicit nil value) in the user map used to build Xray protocol accounts for the handler API. Every protocol branch first pulls its mandatory fields — typically 'email' plus protocol-specific ones like 'publicKey' for wireguard — so this error names exactly which field the inbound's client settings lack.

Source

Thrown at internal/xray/api.go:63

var (
	trafficRegex       = regexp.MustCompile(`(inbound|outbound)>>>([^>]+)>>>traffic>>>(downlink|uplink)`)
	clientTrafficRegex = regexp.MustCompile(`user>>>([^>]+)>>>traffic>>>(downlink|uplink)`)
)

// XrayAPI is a gRPC client for managing Xray core configuration, inbounds, outbounds, and statistics.
type XrayAPI struct {
	HandlerServiceClient *command.HandlerServiceClient
	StatsServiceClient   *statsService.StatsServiceClient
	RoutingServiceClient *routerService.RoutingServiceClient
	grpcClient           *grpc.ClientConn
	isConnected          bool
	StatsLastValues      map[string]int64
}

func getRequiredUserString(user map[string]any, key string) (string, error) {
	value, ok := user[key]
	if !ok || value == nil {
		return "", fmt.Errorf("missing required user field %q", key)
	}

	strValue, ok := value.(string)
	if !ok {
		return "", fmt.Errorf("invalid type for user field %q: %T", key, value)
	}

	return strValue, nil
}

func getOptionalUserString(user map[string]any, key string) (string, error) {
	value, ok := user[key]
	if !ok || value == nil {
		return "", nil
	}

	strValue, ok := value.(string)
	if !ok {

View on GitHub (pinned to ad32144c42)

Solutions

  1. Inspect the error's %q field name, then open the inbound's client entry in the panel and fill in that exact field (e.g. set the client email / wireguard publicKey) and save, which regenerates the user map.
  2. If the field genuinely exists in the stored JSON, check for a nil value — the guard treats nil the same as missing; remove the null or set a real value.
  3. If the error appears right after a panel upgrade on old inbounds, migrate the stored clients (add the now-required field) rather than hand-patching Xray.

Example fix

// before — client map missing email
user := map[string]any{"id": uuidStr, "level": 0}

// after
user := map[string]any{"email": "alice@example.com", "id": uuidStr, "level": 0}
Defensive patterns

Strategy: validation

Validate before calling

// Validate required fields before building the Xray user
required := []string{"email"}
if proto == "wireguard" {
    required = append(required, "publicKey")
}
for _, k := range required {
    if v, ok := user[k]; !ok || v == nil {
        return fmt.Errorf("client settings missing %q", k)
    }
}

Type guard

func hasRequiredUserFields(user map[string]any, keys ...string) bool {
    for _, k := range keys {
        v, ok := user[k]
        if !ok || v == nil {
            return false
        }
        if _, isStr := v.(string); !isStr {
            return false
        }
    }
    return true
}

Try / catch

if err != nil {
    if strings.Contains(err.Error(), "missing required user field") {
        // extract field name from message, fix client entry in panel, no retry
    }
}

Prevention

When it happens

Trigger: Calling the user-add path (AddUser/AlterInbound construction in api.go) with a client map lacking 'email', a wireguard client without 'publicKey', etc. Concretely: malformed client JSON in the inbound settings, an API/manual insertion that skipped a mandatory field, or a protocol handler expecting a field the stored client model never wrote.

Common situations: Hand-edited inbound settings JSON missing a field; a client created through a path that only sets flow/id but not email; wireguard clients created before a version that started requiring publicKey; schema drift between the panel's stored client objects and a newer Xray-core expectation.

Related errors


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