{"record":{"id":"b70118131ce3760d","repo":"XTLS/Xray-core","slug":"can-t-get-inbound-proxy-from-handler","errorCode":null,"errorMessage":"can't get inbound proxy from handler.","messagePattern":"can't get inbound proxy from handler\\.","errorType":"exception","errorClass":"errors.Error","httpStatus":null,"severity":"error","filePath":"app/proxyman/command/command.go","lineNumber":32,"sourceCode":"\tgrpc \"google.golang.org/grpc\"\n)\n\n// InboundOperation is the interface for operations that applies to inbound handlers.\ntype InboundOperation interface {\n\t// ApplyInbound applies this operation to the given inbound handler.\n\tApplyInbound(context.Context, inbound.Handler) error\n}\n\n// OutboundOperation is the interface for operations that applies to outbound handlers.\ntype OutboundOperation interface {\n\t// ApplyOutbound applies this operation to the given outbound handler.\n\tApplyOutbound(context.Context, outbound.Handler) error\n}\n\nfunc getInbound(handler inbound.Handler) (proxy.Inbound, error) {\n\tgi, ok := handler.(proxy.GetInbound)\n\tif !ok {\n\t\treturn nil, errors.New(\"can't get inbound proxy from handler.\")\n\t}\n\treturn gi.GetInbound(), nil\n}\n\n// ApplyInbound implements InboundOperation.\nfunc (op *AddUserOperation) ApplyInbound(ctx context.Context, handler inbound.Handler) error {\n\tp, err := getInbound(handler)\n\tif err != nil {\n\t\treturn err\n\t}\n\tum, ok := p.(proxy.UserManager)\n\tif !ok {\n\t\treturn errors.New(\"proxy is not a UserManager\")\n\t}\n\tmUser, err := op.User.ToMemoryUser()\n\tif err != nil {\n\t\treturn errors.New(\"failed to parse user\").Base(err)\n\t}","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/app/proxyman/command/command.go#L14-L50","documentation":"Returned by getInbound() in app/proxyman/command/command.go:32 when an inbound handler passed to an AlterInbound / GetInboundUsers style operation does not implement the proxy.GetInbound interface. Every inbound handler built by Xray's own proxyman implements GetInbound (exposing its inner proxy.Inbound), so a failure means a non-standard or dynamic handler was registered under that tag.","triggerScenarios":"Calling handlerServer.AlterInbound or GetInboundUsers where the tag resolves to a handler type that is not a standard proxyman inbound — for example a handler injected by another app (metrics' virtual outbound-style handler, or a commander-registered handler).","commonSituations":"API users driving the HandlerService API (AddUser/RemoveUser/GetInboundUsers) against a tag that belongs to an app-internal listener such as the metrics endpoint, or against an inbound created by a custom plugin that did not implement proxy.GetInbound.","solutions":["Confirm the tag in the API request refers to a real user-facing inbound (e.g. vmess/vless/trojan inbound), not an app-internal handler.","List inbounds via ListInbounds to see which tags exist and which proxy each uses.","If writing a custom inbound handler, implement proxy.GetInbound's GetInbound() method."],"exampleFix":"// before — tag points at an app-internal handler\nclient.AlterInbound(ctx, &AlterInboundRequest{Tag: \"metrics_out\", ...})\n\n// after — use a real inbound tag\nclient.AlterInbound(ctx, &AlterInboundRequest{Tag: \"vmss-in\", ...})","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// check the handler exposes its inbound proxy before applying an inbound operation\nif _, ok := handler.(proxy.GetInbound); !ok {\n    return errors.New(\"handler does not expose an inbound proxy\")\n}","tryCatchPattern":"if err := op.ApplyInbound(ctx, handler); err != nil {\n    if strings.Contains(err.Error(), \"can't get inbound proxy\") { skipHandler(handler.Tag()) } else { return err }\n}","preventionTips":["Only target handlers created as standard protocol inbounds.","Custom inbound handlers should implement proxy.GetInbound."],"tags":["go","xray","api","type-assertion","inbound"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}