{"record":{"id":"1185cd1d1e94bbd7","repo":"caddyserver/caddy","slug":"network-type-s-is-reserved","errorCode":null,"errorMessage":"network type %s is reserved","messagePattern":"network type (.+?) is reserved","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"listeners.go","lineNumber":673,"sourceCode":"\t} else if fcql.closed.CompareAndSwap(1, 2) {\n\t\t_, _ = listenerPool.Delete(fcql.sharedQuicListener.key)\n\t}\n\treturn nil\n}\n\n// RegisterNetwork registers a network type with Caddy so that if a listener is\n// created for that network type, getListener will be invoked to get the listener.\n// This should be called during init() and will panic if the network type is standard\n// or reserved, or if it is already registered. EXPERIMENTAL and subject to change.\nfunc RegisterNetwork(network string, getListener ListenerFunc) {\n\tnetwork = strings.TrimSpace(strings.ToLower(network))\n\n\tif network == \"tcp\" || network == \"tcp4\" || network == \"tcp6\" ||\n\t\tnetwork == \"udp\" || network == \"udp4\" || network == \"udp6\" ||\n\t\tnetwork == \"unix\" || network == \"unixpacket\" || network == \"unixgram\" ||\n\t\tstrings.HasPrefix(network, \"ip:\") || strings.HasPrefix(network, \"ip4:\") || strings.HasPrefix(network, \"ip6:\") ||\n\t\tnetwork == \"fd\" || network == \"fdgram\" {\n\t\tpanic(\"network type \" + network + \" is reserved\")\n\t}\n\n\tif _, ok := networkTypes[strings.ToLower(network)]; ok {\n\t\tpanic(\"network type \" + network + \" is already registered\")\n\t}\n\n\tnetworkTypes[network] = getListener\n}\n\nvar unixSocketsMu sync.Mutex\n\n// getListenerFromPlugin returns a listener on the given network and address\n// if a plugin has registered the network name. It may return (nil, nil) if\n// no plugin can provide a listener.\nfunc getListenerFromPlugin(ctx context.Context, network, host, port string, portOffset uint, config net.ListenConfig) (any, error) {\n\t// get listener from plugin if network type is registered\n\tif getListener, ok := networkTypes[network]; ok {\n\t\tLog().Debug(\"getting listener from plugin\", zap.String(\"network\", network))","sourceCodeStart":655,"sourceCodeEnd":691,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/listeners.go#L655-L691","documentation":"RegisterNetwork lets plugins register custom listener network types (called from init()). Standard network names — tcp/tcp4/tcp6, udp/udp4/udp6, unix/unixpacket/unixgram, ip:/ip4:/ip6: prefixes, fd, fdgram — are reserved because Caddy handles them natively. Attempting to register one panics to prevent hijacking core networking.","triggerScenarios":"Calling caddy.RegisterNetwork(\"tcp\", fn), RegisterNetwork(\"unix\", fn), RegisterNetwork(\"fd\", fn), or any name with an ip:/ip4:/ip6: prefix from a plugin's init().","commonSituations":"Writing a listener plugin (e.g. custom socket types, systemd fd passing) and picking a name that collides with a standard network; assuming you can wrap/replace Caddy's TCP listener this way.","solutions":["Choose a non-standard, namespaced network name such as \"myplugin:vsock\" or \"unixgram-custom\"","If you need to intercept standard networks, hook listener wrapping (Server.ListenCallbacks / caddy.Listen) instead of RegisterNetwork","Check the reserved list in listeners.go before naming your network type"],"exampleFix":"// before\nfunc init() {\n    caddy.RegisterNetwork(\"tcp\", myListenerFunc) // reserved\n}\n// after\nfunc init() {\n    caddy.RegisterNetwork(\"myplugin:tcp\", myListenerFunc)\n}","handlingStrategy":"validation","validationCode":"var reservedNetworks = map[string]bool{\n    \"tcp\": true, \"tcp4\": true, \"tcp6\": true,\n    \"udp\": true, \"udp4\": true, \"udp6\": true,\n    \"unix\": true, \"unixpacket\": true, \"unixgram\": true,\n    \"fd\": true, \"fdgram\": true,\n}\n\nfunc isReservedNetwork(n string) bool {\n    n = strings.ToLower(strings.TrimSpace(n))\n    if reservedNetworks[n] {\n        return true\n    }\n    return strings.HasPrefix(n, \"ip:\") || strings.HasPrefix(n, \"ip4:\") || strings.HasPrefix(n, \"ip6:\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Namespace custom network names (vendor:transport)","Register networks only in init()","Read listeners.go's reserved list before adding a type"],"tags":["caddy","go","network","listeners","plugin","panic"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}