v2rayA/v2rayA · error
outboundType must be 'direct' or 'routingA'
Error message
outboundType must be 'direct' or 'routingA'
What it means
The outbound binding of a custom inbound must use outboundType "direct" or "routingA". Any other value is rejected because the config generator only supports these two binding modes for custom inbounds.
Source
Thrown at service/server/controller/customInbound.go:48
if ci.Port <= 0 || ci.Port > 65535 {
common.ResponseError(ctx, logError(fmt.Errorf("invalid port")))
return
}
if ci.Tag == "" {
common.ResponseError(ctx, logError(fmt.Errorf("tag is required")))
return
}
if net.ParseIP("0.0.0.0:"+fmt.Sprint(ci.Port)) == nil {
// basic port check already done above
}
// Validate outbound binding
if ci.Outbound == "" {
common.ResponseError(ctx, logError(fmt.Errorf("outbound group is required")))
return
}
if ci.OutboundType != "direct" && ci.OutboundType != "routingA" {
common.ResponseError(ctx, logError(fmt.Errorf("outboundType must be 'direct' or 'routingA'")))
return
}
// Verify the outbound group exists
outbounds := configure.GetOutbounds()
outboundExists := false
for _, ob := range outbounds {
if ob == ci.Outbound {
outboundExists = true
break
}
}
if !outboundExists {
common.ResponseError(ctx, logError(fmt.Errorf("outbound group '%s' does not exist", ci.Outbound)))
return
}
// If outboundType is "routingA", validate the RoutingA rulesView on GitHub (pinned to 71e5442fc5)
Solutions
- Set outboundType to exactly "direct" or "routingA" (lowercase)
- If per-rule routing is needed, choose "routingA" and supply RoutingARules
- Normalize the enum in the client before sending
Example fix
// before
{"outboundType":"routing-a",...}
// after
{"outboundType":"routingA",...} Defensive patterns
Strategy: validation
Validate before calling
var validOutboundTypes = map[string]bool{"direct":true,"routingA":true}; if !validOutboundTypes[ci.OutboundType] { return fmt.Errorf("outboundType must be direct or routingA") } Type guard
func isValidOutboundType(t string) bool { return t == "direct" || t == "routingA" } Try / catch
if err := postCustomInbound(ci); strings.Contains(err.Error(), "outboundType must be") { ci.OutboundType = normalizeType(ci.OutboundType); retry } Prevention
- Use a dropdown limited to direct/routingA
- Compare case-insensitively then send the canonical value
- Do not confuse outbound tags with binding modes
When it happens
Trigger: POST /custom-inbound with ci.OutboundType not equal to "direct" or "routingA" — e.g. "rule", "freedom", "block", "", or mixed case.
Common situations: Passing a v2ray outbound tag name where the API expects a binding mode; typos like "routing-a" or "RoutingA".
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- protocol must be socks or http
- invalid port
- tag is required
- outbound group is required
- routingA rules are required when outboundType is 'routingA'
AI-assisted analysis of v2rayA/v2rayA@71e5442fc5 (2026-09-05).
Data as JSON: /api/errors/873f04210de8ba70.
Report an issue: GitHub.