{"record":{"id":"9eb84ee0825b73b4","repo":"ipfs/kubo","slug":"protocol-name-must-be-within-p2p-namespace","errorCode":null,"errorMessage":"protocol name must be within '/p2p/' namespace","messagePattern":"protocol name must be within '/p2p/' namespace","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/commands/p2p.go","lineNumber":161,"sourceCode":"\t\tlistenOpt := req.Arguments[1]\n\t\ttargetOpt := req.Arguments[2]\n\n\t\tproto := protocol.ID(protoOpt)\n\n\t\tlisten, err := ma.NewMultiaddr(listenOpt)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\ttargets, err := parseIpfsAddr(targetOpt)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tallowCustom, _ := req.Options[allowCustomProtocolOptionName].(bool)\n\n\t\tif !allowCustom && !strings.HasPrefix(string(proto), P2PProtoPrefix) {\n\t\t\treturn errors.New(\"protocol name must be within '\" + P2PProtoPrefix + \"' namespace\")\n\t\t}\n\n\t\tlistener, err := forwardLocal(n.Context(), n.P2P, n.Peerstore, proto, listen, targets)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tforeground, _ := req.Options[foregroundOptionName].(bool)\n\t\tif foreground {\n\t\t\tif err := res.Emit(&P2PForegroundOutput{\n\t\t\t\tStatus:   \"active\",\n\t\t\t\tProtocol: protoOpt,\n\t\t\t\tAddress:  listenOpt,\n\t\t\t}); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\t// Wait for either context cancellation (Ctrl+C/daemon shutdown)\n\t\t\t// or listener removal (ipfs p2p close)","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/core/commands/p2p.go#L143-L179","documentation":"`ipfs p2p forward` (local forwarding) reserves the `/p2p/` protocol namespace for kubo's built-in p2p protocols. Unless the caller passes the `--allow-custom-protocol` option, the requested protocol ID must start with the P2PProtoPrefix (`/p2p/`); otherwise the command refuses before opening the listener.","triggerScenarios":"Running `ipfs p2p forward <proto> <listen> <target>` where proto does not begin with `/p2p/` and `--allow-custom-protocol` (allowCustomProtocolOptionName) is not set, e.g. `ipfs p2p forward tcp/8080 ...`.","commonSituations":"Users porting plain TCP forwarding examples that use bare protocol names; forgetting the required `/p2p/` prefix such as `/x/custom` instead of `/p2p/x/custom` or omitting the flag when intentionally using a custom namespace.","solutions":["Prefix the protocol with `/p2p/`, e.g. `ipfs p2p forward /p2p/myapp/1.0.0 /ip4/127.0.0.1/tcp/8080 <target>`.","If the custom namespace is intentional, add `--allow-custom-protocol` to the command.","Ensure the same protocol string is used on both ends (listen and dial) of the tunnel."],"exampleFix":"// before\nipfs p2p forward myapp/1.0.0 /ip4/127.0.0.1/tcp/8080 <peerid>\n// after\nipfs p2p forward /p2p/myapp/1.0.0 /ip4/127.0.0.1/tcp/8080 <peerid>   # or add --allow-custom-protocol","handlingStrategy":"validation","validationCode":"const p2pPrefix = \"/p2p/\"\nproto := \"myapp/1.0.0\"\nif !strings.HasPrefix(proto, p2pPrefix) {\n    proto = p2pPrefix + proto // or add --allow-custom-protocol\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always name p2p tunnel protocols under /p2p/ unless you deliberately pass --allow-custom-protocol.","Share a single protocol-string constant between listen and dial sides.","Sanitize user-supplied protocol input to enforce the prefix."],"tags":["p2p","cli","validation"],"backgroundTag":"invalid-protocol-namespace","analyzedSha":"329838acdfafae224582930457efe80aa217afc0","analyzedAt":"2026-09-03T18:30:52.135Z","contentChangedAt":"2026-09-03T18:30:52.135Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}