{"record":{"id":"c941c88f661af6a3","repo":"ipfs/kubo","slug":"private-key-in-config-was-not-a-string","errorCode":null,"errorMessage":"private key in config was not a string","messagePattern":"private key in config was not a string","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/commands/config.go","lineNumber":634,"sourceCode":"\teditor = editorAndArgs[0]\n\targs := append(editorAndArgs[1:], filename)\n\n\tcmd := exec.Command(editor, args...)\n\tcmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr\n\treturn cmd.Run()\n}\n\n// nodePeerID derives the PeerID implied by the private key stored in the repo\n// config. Identity.PeerID must equal this value; the node refuses to start\n// when the two disagree.\nfunc nodePeerID(r repo.Repo) (peer.ID, error) {\n\tkeyF, err := getConfig(r, config.PrivKeySelector)\n\tif err != nil {\n\t\treturn \"\", errors.New(\"failed to get PrivKey\")\n\t}\n\tpkstr, ok := keyF.Value.(string)\n\tif !ok {\n\t\treturn \"\", errors.New(\"private key in config was not a string\")\n\t}\n\tident := config.Identity{PrivKey: pkstr}\n\tpk, err := ident.DecodePrivateKey(\"\")\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to decode PrivKey: %w\", err)\n\t}\n\tid, err := peer.IDFromPrivateKey(pk)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to derive PeerID from PrivKey: %w\", err)\n\t}\n\treturn id, nil\n}\n\nfunc replaceConfig(r repo.Repo, file io.Reader) error {\n\tvar newCfg config.Config\n\tif err := json.NewDecoder(file).Decode(&newCfg); err != nil {\n\t\treturn errors.New(\"failed to decode file as config\")\n\t}","sourceCodeStart":616,"sourceCodeEnd":652,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/core/commands/config.go#L616-L652","documentation":"After fetching the PrivKey config field, nodePeerID asserts the value is a Go string. This error fires if Identity.PrivKey exists in the config but is not a string (e.g. stored as a JSON object, number, or array). A base64-encoded key string is required to decode the private key.","triggerScenarios":"Hand-editing config.json so Identity.PrivKey becomes a non-string JSON value; programmatic config manipulation that sets Identity.PrivKey to an object/array; a corrupted config where the field type changed.","commonSituations":"Users pasting the key as nested JSON (e.g. {\"Type\":0,\"Data\":...}) instead of the expected base64 string produced by `ipfs key export`/init; scripted config edits with jq that accidentally restructure the field.","solutions":["Restore Identity.PrivKey to the base64 string format: `ipfs config show | jq .Identity.PrivKey` should print a quoted string","Re-set it as a string: `ipfs config --json Identity.PrivKey '\"<base64-key>\"'` (then verify with `ipfs id` after daemon restart)","If the raw key material was destroyed, re-init the repo or restore from backup — the PeerID changes otherwise","Avoid hand-editing Identity via scripts; use `ipfs config replace` with a file that preserves the original Identity block"],"exampleFix":"// before (config.json)\n\"Identity\": { \"PrivKey\": { \"Type\": 0, \"Data\": \"...\" } }\n// after\n\"Identity\": { \"PrivKey\": \"CAESQA==...base64...\" }","handlingStrategy":"type-guard","validationCode":"key=$(ipfs config show | jq -r '.Identity.PrivKey'); case \"$(echo -n \"$key\" | jq -R 'fromjson? | type' 2>/dev/null)\" in null|\"\\\"string\\\"\") ;; *) echo \"PrivKey is not a JSON string\" ;; esac","typeGuard":"func isStringPrivKey(v any) (string, bool) {\n    s, ok := v.(string)\n    return s, ok // ok==false means Identity.PrivKey is a non-string JSON value\n}","tryCatchPattern":"keyF, err := getConfig(r, config.PrivKeySelector)\nif err != nil { return err }\npkstr, ok := keyF.Value.(string)\nif !ok {\n    return fmt.Errorf(\"Identity.PrivKey must be a base64 string, got %T\", keyF.Value)\n}","preventionTips":["Store PrivKey only as the base64 string kubo generates at init","Never let jq/scripts restructure Identity.PrivKey into nested JSON","Validate config.json with jq (check types) after scripted edits","Use `ipfs config --json Identity.PrivKey '\"<b64>\"'` to set it correctly"],"tags":["config","identity","type-error"],"backgroundTag":"privkey-invalid-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"}