{"record":{"id":"40d945d60b3a71bd","repo":"netbirdio/netbird","slug":"invalid-mtu-w","errorCode":null,"errorMessage":"invalid MTU: %w","messagePattern":"invalid MTU: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/embed/embed.go","lineNumber":157,"sourceCode":"\tif credentialsProvided == 0 {\n\t\treturn fmt.Errorf(\"one of SetupKey, JWTToken, or PrivateKey must be provided\")\n\t}\n\tif credentialsProvided > 1 {\n\t\treturn fmt.Errorf(\"only one of SetupKey, JWTToken, or PrivateKey can be specified\")\n\t}\n\n\treturn nil\n}\n\n// New creates a new netbird embedded client.\nfunc New(opts Options) (*Client, error) {\n\tif err := opts.validateCredentials(); err != nil {\n\t\treturn nil, err\n\t}\n\n\tif opts.MTU != nil {\n\t\tif err := iface.ValidateMTU(*opts.MTU); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid MTU: %w\", err)\n\t\t}\n\t}\n\n\tif opts.LogOutput != nil {\n\t\tlogrus.SetOutput(opts.LogOutput)\n\t}\n\n\tif opts.LogLevel != \"\" {\n\t\tlevel, err := logrus.ParseLevel(opts.LogLevel)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"parse log level: %w\", err)\n\t\t}\n\t\tlogrus.SetLevel(level)\n\t}\n\n\tif !opts.NoUserspace {\n\t\tif err := os.Setenv(netstack.EnvUseNetstackMode, \"true\"); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"setenv: %w\", err)","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/embed/embed.go#L139-L175","documentation":"Returned by embed.New when Options.MTU is non-nil and fails iface.ValidateMTU, which enforces the range 576..8192 bytes (MinMTU/MaxMTU in client/iface/iface.go). The MTU is validated eagerly at construction so an out-of-range value never reaches the tunnel interface. The wrapped error states whether the value is below the minimum or above the maximum.","triggerScenarios":"Calling embed.New with MTU set to a pointer holding a value < 576 (e.g. 512 or 0 copied from a default uint16) or > 8192 (e.g. 9000 'jumbo frame' values or a value read from a config that used a different unit).","commonSituations":"Copying an MTU tuned for a physical NIC (1500/9000) into the overlay config; treating 0 as 'unset' while the API uses a nil pointer for 'unset'; reading MTU from a JSON/YAML config as int and truncating/overflowing into uint16.","solutions":["Set Options.MTU to a value in 576..8192; 1280 is the default (iface.DefaultMTU) and 1400 is typical when carrying QUIC.","Leave Options.MTU nil to keep the existing config MTU or fall back to the default instead of passing 0.","Call iface.ValidateMTU(mtu) yourself before embed.New to produce the error at your own validation boundary with your own message."],"exampleFix":"// before\nmtu := uint16(0) // means \"unset\" in the caller's config\nclient, err := embed.New(embed.Options{MTU: &mtu})\n\n// after\nvar mtu *uint16\nif cfgMTU > 0 {\n    m := uint16(cfgMTU)\n    mtu = &m\n}\nclient, err := embed.New(embed.Options{MTU: mtu})","handlingStrategy":"validation","validationCode":"import \"github.com/netbirdio/netbird/client/iface\"\n\nif opts.MTU != nil {\n    if err := iface.ValidateMTU(*opts.MTU); err != nil {\n        return fmt.Errorf(\"reject options before embed.New: %w\", err)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Centralize MTU construction in one helper that only produces values in 576..8192 or nil.","Treat 0 as 'unset' and convert it to a nil *uint16 before passing Options."],"tags":["config","mtu","validation","embed"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}