{"record":{"id":"fa853b252eb41ef1","repo":"ipfs/kubo","slug":"invalid-key","errorCode":null,"errorMessage":"invalid key","messagePattern":"invalid key","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/coreapi/routing.go","lineNumber":65,"sourceCode":"\terr = api.checkOnline(options.AllowOffline)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tdhtKey, err := normalizeKey(key)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn api.routing.PutValue(ctx, dhtKey, value)\n}\n\nfunc normalizeKey(s string) (string, error) {\n\tparts := strings.Split(s, \"/\")\n\tif len(parts) != 3 ||\n\t\tparts[0] != \"\" ||\n\t\t!(parts[1] == \"ipns\" || parts[1] == \"pk\") {\n\t\treturn \"\", errors.New(\"invalid key\")\n\t}\n\n\tk, err := peer.Decode(parts[2])\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn strings.Join(append(parts[:2], string(k)), \"/\"), nil\n}\n\nfunc (api *RoutingAPI) FindPeer(ctx context.Context, p peer.ID) (peer.AddrInfo, error) {\n\tctx, span := tracing.Span(ctx, \"CoreAPI.DhtAPI\", \"FindPeer\", trace.WithAttributes(attribute.String(\"peer\", p.String())))\n\tdefer span.End()\n\terr := api.checkOnline(false)\n\tif err != nil {\n\t\treturn peer.AddrInfo{}, err\n\t}\n\n\tpi, err := api.routing.FindPeer(ctx, peer.ID(p))","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/core/coreapi/routing.go#L47-L83","documentation":"normalizeKey validates an IPNS/pk routing key path, which must have the form /ipns/<peerid> or /pk/<peerid> (three slash-separated parts, empty first). Anything else — wrong prefix, missing parts, extra slashes — returns \"invalid key\" before the peer ID is even decoded. It is a strict path-format validation.","triggerScenarios":"Calling Routing().Get or Routing().Put with keys like \"ipns/foo\", \"/ipns\", \"/ipfs/foo\", \"/pk/<id>/extra\", or a raw peer id without the leading slash and namespace.","commonSituations":"Scripts that build the key path by hand and forget the leading slash, using the wrong namespace prefix (ipfs instead of ipns/pk), and passing CIDs or DNSNames where a peer ID is required.","solutions":["Format the key as /ipns/<peerID> or /pk/<peerID>, with leading slash and exactly three segments.","Ensure the third segment decodes as a valid libp2p peer ID (use peer.Decode-compatible formats).","Build the path with fmt.Sprintf(\"/ipns/%s\", id) from a peer.ID rather than concatenating strings.","If the value is a DNSLink name, resolve it to a peer ID first — DNS names are not valid here."],"exampleFix":"// before\nval, err := api.Routing().Get(ctx, \"ipns/12D3KooW...\")\n// after\nval, err := api.Routing().Get(ctx, \"/ipns/12D3KooW...\")","handlingStrategy":"validation","validationCode":"func validRoutingKey(s string) bool {\n\tparts := strings.Split(s, \"/\")\n\tif len(parts) != 3 || parts[0] != \"\" || (parts[1] != \"ipns\" && parts[1] != \"pk\") {\n\t\treturn false\n\t}\n\t_, err := peer.Decode(parts[2])\n\treturn err == nil\n}","typeGuard":"func toRoutingKey(id peer.ID) (string, bool) {\n\tif id == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn \"/ipns/\" + id.String(), true\n}","tryCatchPattern":"val, err := api.Routing().Get(ctx, key)\nif err != nil && strings.Contains(err.Error(), \"invalid key\") {\n\treturn fmt.Errorf(\"key %q must be /ipns/<peerid> or /pk/<peerid>: %w\", key, err)\n}","preventionTips":["Build keys with fmt.Sprintf(\"/ipns/%s\", peerID) instead of manual concatenation","Decode the peer ID with peer.Decode before forming the path","Never pass DNS names or CIDs where a peer ID is required"],"tags":["ipfs","ipns","routing","input-validation"],"backgroundTag":"invalid-key-format","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"}