{"record":{"id":"0dca82b10ef33f4f","repo":"XTLS/Xray-core","slug":"not-an-inbound-operation","errorCode":null,"errorMessage":"not an inbound operation","messagePattern":"not an inbound operation","errorType":"exception","errorClass":"errors.Error","httpStatus":null,"severity":"error","filePath":"app/proxyman/command/command.go","lineNumber":92,"sourceCode":"\tif err := core.AddInboundHandler(s.s, request.Inbound); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &AddInboundResponse{}, nil\n}\n\nfunc (s *handlerServer) RemoveInbound(ctx context.Context, request *RemoveInboundRequest) (*RemoveInboundResponse, error) {\n\treturn &RemoveInboundResponse{}, s.ihm.RemoveHandler(ctx, request.Tag)\n}\n\nfunc (s *handlerServer) AlterInbound(ctx context.Context, request *AlterInboundRequest) (*AlterInboundResponse, error) {\n\trawOperation, err := request.Operation.GetInstance()\n\tif err != nil {\n\t\treturn nil, errors.New(\"unknown operation\").Base(err)\n\t}\n\toperation, ok := rawOperation.(InboundOperation)\n\tif !ok {\n\t\treturn nil, errors.New(\"not an inbound operation\")\n\t}\n\n\thandler, err := s.ihm.GetHandler(ctx, request.Tag)\n\tif err != nil {\n\t\treturn nil, errors.New(\"failed to get handler: \", request.Tag).Base(err)\n\t}\n\n\treturn &AlterInboundResponse{}, operation.ApplyInbound(ctx, handler)\n}\n\nfunc (s *handlerServer) ListInbounds(ctx context.Context, request *ListInboundsRequest) (*ListInboundsResponse, error) {\n\thandlers := s.ihm.ListHandlers(ctx)\n\tresponse := &ListInboundsResponse{}\n\tif request.GetIsOnlyTags() {\n\t\tfor _, handler := range handlers {\n\t\t\tresponse.Inbounds = append(response.Inbounds, &core.InboundHandlerConfig{\n\t\t\t\tTag: handler.Tag(),\n\t\t\t})","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/app/proxyman/command/command.go#L74-L110","documentation":"Returned by handlerServer.AlterInbound (app/proxyman/command/command.go:92) when the deserialized operation object does not implement the InboundOperation interface (ApplyInbound method). The type resolved successfully (error 54 did not fire) but it is not an inbound-side operation — e.g. an outbound operation was sent to AlterInbound.","triggerScenarios":"Sending an operation intended for AlterOutbound (or any random registered config type) in an AlterInboundRequest. The Any's type_url must reference a type implementing InboundOperation.","commonSituations":"API client bugs that mix up the inbound/outbound operation envelopes; future operation types that only implement ApplyOutbound.","solutions":["Use AddUserOperation/RemoveUserOperation (the currently defined inbound operations) with AlterInbound.","Double-check the request type: outbound-directed operations go through AlterOutbound.","If defining custom operations, implement ApplyInbound(context.Context, inbound.Handler) error for inbound use."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// client-side: ensure the payload is a known inbound operation before sending\nfunc isInboundOperation(t string) bool {\n    return t == \"xray.app.proxyman.command.AddUserOperation\" ||\n           t == \"xray.app.proxyman.command.RemoveUserOperation\"\n}","tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"not an inbound operation\") {\n    return errors.New(\"sent an outbound/unknown operation to AlterInbound; fix request envelope\")\n}","preventionTips":["Keep separate request builders for AlterInbound vs AlterOutbound.","Custom operations must implement ApplyInbound to be usable on the inbound path."],"tags":["go","xray","api","type-assertion","protobuf"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}