{"record":{"id":"e3e29d7af0fabf97","repo":"caddyserver/caddy","slug":"network-type-s-is-already-registered","errorCode":null,"errorMessage":"network type %s is already registered","messagePattern":"network type (.+?) is already registered","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"listeners.go","lineNumber":677,"sourceCode":"}\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))\n\t\treturn getListener(ctx, network, host, port, portOffset, config)\n\t}\n\n\treturn nil, nil","sourceCodeStart":659,"sourceCodeEnd":695,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/listeners.go#L659-L695","documentation":"RegisterNetwork maintains a global registry of custom network types; registering the same (case-insensitive, trimmed) name twice panics. This usually means two plugins claim the same network name, or one plugin registers in multiple init paths. The panic fires during process startup, before serving.","triggerScenarios":"Two plugins both calling caddy.RegisterNetwork(\"vsock\", fn); or a plugin registered twice via duplicate blank imports / vendored twice under different paths.","commonSituations":"Name collisions between third-party listener plugins; accidentally importing a plugin package twice (e.g. direct import plus inclusion in a build tag variant); forking a plugin and shipping both fork and original in one binary.","solutions":["Give your network type a unique namespaced name (e.g. \"acme:wire\")","Check which plugins are compiled in: caddy list-modules --packages, and remove the duplicate import","If you forked a plugin, exclude the original from the build (replace/drop the import)"],"exampleFix":"// before\n// plugin A and plugin B both:\nfunc init() { caddy.RegisterNetwork(\"tunnel\", fnA) }\n// after\n// plugin A:\nfunc init() { caddy.RegisterNetwork(\"acme:tunnel\", fnA) }\n// plugin B:\nfunc init() { caddy.RegisterNetwork(\"othercorp:tunnel\", fnB) }","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefix network names with a plugin/vendor identifier","Audit linked plugins with caddy list-modules --packages","Use go.mod replace to collapse duplicate plugin copies"],"tags":["caddy","go","network","plugin","duplicate-registration","panic"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}