XTLS/Xray-core · error
failed to build mask with type + mask.Type
Error message
failed to build mask with type + mask.Type
What it means
Thrown when a TCP mask entry under streamSettings.finalMask.tcp fails to build (mask.Build(true) errors). The error text interpolates mask.Type, so it tells you which mask implementation rejected its own configuration (e.g. an unrecognized or misconfigured TCP mask type). It stops config compilation immediately.
Source
Thrown at infra/conf/transport_internet.go:207
}
config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
ProtocolName: "hysteria",
Settings: serial.ToTypedMessage(hs),
})
}
if c.SocketSettings != nil {
ss, err := c.SocketSettings.Build()
if err != nil {
return nil, errors.New("Failed to build sockopt.").Base(err)
}
config.SocketSettings = ss
}
if c.FinalMask != nil {
for _, mask := range c.FinalMask.Tcp {
u, err := mask.Build(true)
if err != nil {
return nil, errors.New("failed to build mask with type ", mask.Type).Base(err)
}
config.Tcpmasks = append(config.Tcpmasks, serial.ToTypedMessage(u))
}
for _, mask := range c.FinalMask.Udp {
u, err := mask.Build(false)
if err != nil {
return nil, errors.New("failed to build mask with type ", mask.Type).Base(err)
}
config.Udpmasks = append(config.Udpmasks, serial.ToTypedMessage(u))
}
if c.FinalMask.QuicParams != nil {
profile := strings.ToLower(c.FinalMask.QuicParams.BbrProfile)
switch profile {
case "", string(bbr.ProfileConservative), string(bbr.ProfileStandard), string(bbr.ProfileAggressive):
if profile == "" {
profile = string(bbr.ProfileStandard)
}
default:View on GitHub (pinned to 7d214f8b09)
Solutions
- Check the mask.Type value in the error against the registered TCP mask types in the codebase; fix typos or unsupported types.
- Validate the per-type fields required by that mask implementation.
- Remove the offending mask entry to isolate whether other mask entries build fine.
Example fix
// before
"finalMask": { "tcp": [ { "type": "typoMask", "window": 10 } ] }
// after
"finalMask": { "tcp": [ { "type": "windowMask", "window": 10 } ] } // use a registered type Defensive patterns
Strategy: validation
Validate before calling
var validTcpMaskTypes = map[string]bool{"window": true /* ...populate from this build's registry... */}
func tcpMasksValid(fm map[string]any) bool {
tcp, _ := fm["tcp"].([]any)
for _, m := range tcp {
mm, _ := m.(map[string]any)
t, _ := mm["type"].(string)
if !validTcpMaskTypes[t] { return false }
}
return true
} Type guard
func isFinalMaskTcpList(fm map[string]any) bool {
_, ok := fm["tcp"].([]any)
return ok
} Try / catch
if err := doc.Build(); err != nil {
if strings.HasPrefix(err.Error(), "failed to build mask with type") {
// extract the type token from the message and report which entry failed
}
return err
} Prevention
- Maintain an allow-list of mask types validated in CI against the deployed binary.
- Name each mask entry in comments/templates so failures map to a source location.
- Never carry mask blocks across forks without re-validating types.
When it happens
Trigger: Config contains "finalMask": { "tcp": [ { "type": "<something>", ... } ] } and the mask's Build() returns an error for that type's parameters.
Common situations: Using a mask type name not registered/supported by this build; supplying wrong per-type fields; configs ported from a fork with extra mask types.
Related errors
- bridge tag is empty
- bridge domain is empty
- portal tag is empty
- portal domain is empty
- unknown action: {}
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/3f093aa728a8a03d.
Report an issue: GitHub.