XTLS/Xray-core · error · errors.Error
proxy is not a UserManager
Error message
proxy is not a UserManager
What it means
Returned by AddUserOperation.ApplyInbound (app/proxyman/command/command.go:45) when the inbound handler's proxy does not implement proxy.UserManager. Only user-capable protocols (VMess, VLESS, Trojan, Shadowsocks, etc.) support runtime AddUser; protocol inbounds like dokodemo-door or a mis-tagged outbound-style handler reject user operations.
Source
Thrown at app/proxyman/command/command.go:45
}
func getInbound(handler inbound.Handler) (proxy.Inbound, error) {
gi, ok := handler.(proxy.GetInbound)
if !ok {
return nil, errors.New("can't get inbound proxy from handler.")
}
return gi.GetInbound(), nil
}
// ApplyInbound implements InboundOperation.
func (op *AddUserOperation) ApplyInbound(ctx context.Context, handler inbound.Handler) error {
p, err := getInbound(handler)
if err != nil {
return err
}
um, ok := p.(proxy.UserManager)
if !ok {
return errors.New("proxy is not a UserManager")
}
mUser, err := op.User.ToMemoryUser()
if err != nil {
return errors.New("failed to parse user").Base(err)
}
return um.AddUser(ctx, mUser)
}
// ApplyInbound implements InboundOperation.
func (op *RemoveUserOperation) ApplyInbound(ctx context.Context, handler inbound.Handler) error {
p, err := getInbound(handler)
if err != nil {
return err
}
um, ok := p.(proxy.UserManager)
if !ok {
return errors.New("proxy is not a UserManager")
}View on GitHub (pinned to 7d214f8b09)
Solutions
- Target an inbound whose protocol supports users (vless/vmess/trojan/shadowsocks).
- Verify the inbound tag with ListInbounds before issuing AddUser.
- If you must add users dynamically, ensure the inbound was created through the API with the right settings.
Example fix
// before — dokodemo-door cannot hold users
req := &ModifyInboundRequest{InboundTag: "dokodemo-in", Operation: addUserOp}
// after — add to a VLESS inbound
req := &ModifyInboundRequest{InboundTag: "vless-in", Operation: addUserOp} Defensive patterns
Strategy: type-guard
Type guard
// check the inbound proxy supports users before AddUser
if p, ok := handler.(proxy.GetInbound); ok {
if _, ok := p.GetInbound().(proxy.UserManager); ok {
// safe to add user
}
} Try / catch
if err := addOp.ApplyInbound(ctx, handler); err != nil {
if strings.Contains(err.Error(), "not a UserManager") { continue /* non-user inbound */ } else { return err }
} Prevention
- Maintain a set of user-capable protocol names (vless, vmess, trojan, shadowsocks) and filter targets.
- Validate inbound protocol from ListInbounds before user operations.
When it happens
Trigger: Calling the HandlerService API's alterInbound with AddUserOperation for an inbound whose proxy type has no user concept — most often dokodemo-door, socks/http inbound (non-user-managed variants), or liberty/mixed handlers configured without user auth.
Common situations: Panels and automation tools that add users to whatever tag the operator typed; a typo in the tag resolving to the wrong inbound, or the panel assuming every inbound is a multi-user proxy.
Related errors
- can't get inbound proxy from handler.
- failed to parse user
- not an inbound operation
- unknown operation
- failed to get handler:
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/25fe92a651e04c56.
Report an issue: GitHub.