{"record":{"id":"c1cf8b75191fdfc1","repo":"juanfont/headscale","slug":"converting-private-key-to-string-for-saving-w","errorCode":null,"errorMessage":"converting private key to string for saving: %w","messagePattern":"converting private key to string for saving: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"hscontrol/app.go","lineNumber":971,"sourceCode":"}\n\nfunc readOrCreatePrivateKey(path string) (*key.MachinePrivate, error) {\n\tdir := filepath.Dir(path)\n\n\terr := util.EnsureDir(dir)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"ensuring private key directory: %w\", err)\n\t}\n\n\tprivateKey, err := os.ReadFile(path)\n\tif errors.Is(err, os.ErrNotExist) {\n\t\tlog.Info().Str(\"path\", path).Msg(\"no private key file at path, creating...\")\n\n\t\tmachineKey := key.NewMachine()\n\n\t\tmachineKeyStr, err := machineKey.MarshalText()\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\n\t\t\t\t\"converting private key to string for saving: %w\",\n\t\t\t\terr,\n\t\t\t)\n\t\t}\n\n\t\terr = os.WriteFile(path, machineKeyStr, privateKeyFileMode)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\n\t\t\t\t\"saving private key to disk at path %q: %w\",\n\t\t\t\tpath,\n\t\t\t\terr,\n\t\t\t)\n\t\t}\n\n\t\treturn &machineKey, nil\n\t} else if err != nil {\n\t\treturn nil, fmt.Errorf(\"reading private key file: %w\", err)\n\t}","sourceCodeStart":953,"sourceCodeEnd":989,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/hscontrol/app.go#L953-L989","documentation":"Returned by readOrCreatePrivateKey when key.NewMachine().MarshalText() fails while persisting a newly generated noise private key (hscontrol/app.go:969). MachinePrivate.MarshalText encodes the key to its textual form; for a valid in-memory key this operation is effectively infallible in tailscale.com/util/key — this error is a defensive guard that essentially never fires in practice.","triggerScenarios":"Only conceivable if the key type's MarshalText signature gains a failure mode in a future tailscale.com/util/key version (e.g. invalid internal state). No current input, config, or environment triggers it.","commonSituations":"Virtually none; if it appears, it indicates a corrupted build or an incompatible tailscale library version linked into a custom compile of headscale.","solutions":["Rebuild/reinstall headscale from a clean checkout so the vendored tailscale.com/util/key version matches (go mod tidy && make build).","If maintaining a fork, verify the vendored key package is unmodified.","Treat as a build-environment problem: clear the module cache (go clean -modcache) and rebuild."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Practically unreachable; treat any occurrence as a build/library mismatch.\nif err := h.Serve(); err != nil && strings.Contains(err.Error(), \"converting private key to string\") {\n    log.Fatal().Msg(\"binary built against incompatible tailscale key package; rebuild cleanly\")\n}","preventionTips":["Build from a clean checkout with the repo's pinned toolchain (nix develop && make build).","Do not fork or patch vendored tailscale.com/util/key."],"tags":["crypto-keys","internal","startup","unreachable-in-practice"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}