{"record":{"id":"2e95f292f09ce4c8","repo":"netbirdio/netbird","slug":"path-rewrite-is-not-supported-for-l4-services","errorCode":null,"errorMessage":"path_rewrite is not supported for L4 services","messagePattern":"path_rewrite is not supported for L4 services","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"management/internals/modules/reverseproxy/service/service.go","lineNumber":1069,"sourceCode":"\t\t// target_id carries the cluster address; the proxy resolves\n\t\t// the upstream at request time.\n\tdefault:\n\t\treturn fmt.Errorf(\"invalid target_type %q for L4 service\", target.TargetType)\n\t}\n\tif target.Path != nil && *target.Path != \"\" && *target.Path != \"/\" {\n\t\treturn errors.New(\"path is not supported for L4 services\")\n\t}\n\tif target.Options.SessionIdleTimeout < 0 {\n\t\treturn errors.New(\"session_idle_timeout must be positive for L4 services\")\n\t}\n\tif target.Options.RequestTimeout < 0 {\n\t\treturn errors.New(\"request_timeout must be positive for L4 services\")\n\t}\n\tif target.Options.SkipTLSVerify {\n\t\treturn errors.New(\"skip_tls_verify is not supported for L4 services\")\n\t}\n\tif target.Options.PathRewrite != \"\" {\n\t\treturn errors.New(\"path_rewrite is not supported for L4 services\")\n\t}\n\tif len(target.Options.CustomHeaders) > 0 {\n\t\treturn errors.New(\"custom_headers is not supported for L4 services\")\n\t}\n\treturn nil\n}\n\n// Service mode constants.\nconst (\n\tModeHTTP = \"http\"\n\tModeTCP  = \"tcp\"\n\tModeUDP  = \"udp\"\n\tModeTLS  = \"tls\"\n)\n\n// Target protocol constants (URL scheme for backend connections).\nconst (\n\tTargetProtoHTTP  = \"http\"","sourceCodeStart":1051,"sourceCodeEnd":1087,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/management/internals/modules/reverseproxy/service/service.go#L1051-L1087","documentation":"Returned by validateL4Target when target.options.path_rewrite is non-empty. Path rewriting edits the HTTP request path before proxying; an L4 service never parses the byte stream, so there is no path to rewrite. It is one of a family of HTTP-only options (path, custom_headers, skip_tls_verify) that validateL4Target rejects so misconfigured HTTP configs fail at API time instead of silently misbehaving.","triggerScenarios":"An L4 target carrying \"path_rewrite\": \"strip-prefix\" (or any non-empty mode value) inherited from an HTTP service definition; shared option blocks templated across services of different modes.","commonSituations":"Converting an HTTP service that stripped an /api prefix into a tcp forward and leaving the rewrite rule. Configuration modules that always emit a path_rewrite key.","solutions":["Remove path_rewrite (set it to empty) from the L4 target's options.","Keep the rewrite only on http-mode targets where it is honored.","Split shared templates so mode-inapplicable option keys are not emitted for tcp/udp/tls."],"exampleFix":"// before\n\"options\": { \"path_rewrite\": \"strip-prefix\" }\n\n// after\n\"options\": {}","handlingStrategy":"validation","validationCode":"func checkL4NoPathRewrite(o TargetOptions) error {\n\tif o.PathRewrite != \"\" {\n\t\treturn errors.New(\"path_rewrite is http-only; remove it from L4 targets\")\n\t}\n\treturn nil\n}","typeGuard":"func isL4PathRewriteClean(o TargetOptions) bool {\n\treturn o.PathRewrite == \"\"\n}","tryCatchPattern":"if err := svc.Validate(); err != nil {\n\tif strings.Contains(err.Error(), \"path_rewrite is not supported for L4\") {\n\t\treturn respondBadRequest(errors.New(\"clear path_rewrite on L4 targets\"))\n\t}\n\treturn respondBadRequest(err)\n}","preventionTips":["Keep an explicit list of HTTP-only options and exclude them from L4 payload generation.","When converting an http service to L4, rebuild options from scratch rather than editing.","Assert the options block for L4 targets is empty (or timeout-only) in config tests."],"tags":["netbird","reverse-proxy","validation","l4","path-rewrite","options","go"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}