{"record":{"id":"66b8f6d076466335","repo":"OpenNHP/opennhp","slug":"failed-to-create-device-from-new-key","errorCode":null,"errorMessage":"failed to create device from new key","messagePattern":"failed to create device from new key","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"endpoints/agent/udpagent.go","lineNumber":578,"sourceCode":"func (a *UdpAgent) PublicKeyBase64ByCipherScheme() string {\n\tif a.config.DefaultCipherScheme == common.CIPHER_SCHEME_GMSM {\n\t\treturn a.device.PublicKeyExBase64()\n\t}\n\treturn a.device.PublicKeyBase64()\n}\n\n// PrivateKeyBase64 returns the agent's private key in base64 encoding.\nfunc (a *UdpAgent) PrivateKeyBase64() string {\n\treturn a.config.PrivateKeyBase64\n}\n\n// ReinitWithKey stops the current device, creates a new one from the given\n// private key bytes, and re-adds all known server peers. Call this after\n// Start() when a fresh key pair has been generated for registration.\nfunc (a *UdpAgent) ReinitWithKey(privKeyBytes []byte, cipherScheme int) error {\n\tnewDev := core.NewDevice(core.NHP_AGENT, privKeyBytes, nil)\n\tif newDev == nil {\n\t\treturn fmt.Errorf(\"failed to create device from new key\")\n\t}\n\tnewDev.Start()\n\n\t// Swap in the new device and repoint the receive channel atomically.\n\t// Without repointing recvMsgCh, the old routine keeps reading the old\n\t// (about-to-be-closed) DecryptedMsgQueue and nothing drains the new\n\t// device's queue — cookie challenges and generic replies would be\n\t// silently dropped after a reinit.\n\t//\n\t// Scope note: deviceMutex only synchronizes this swap window and the\n\t// receive routine's channel capture. The send/knock/request paths and\n\t// packetReceiveRoutine read a.device WITHOUT the lock. That is safe for\n\t// the current one-shot register flow — ReinitWithKey runs right after\n\t// Start() while senders are idle, and a.device is never rewritten\n\t// afterward. If ReinitWithKey is ever called with active traffic, those\n\t// readers must also take deviceMutex.\n\ta.deviceMutex.Lock()\n\toldDev := a.device","sourceCodeStart":560,"sourceCodeEnd":596,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/endpoints/agent/udpagent.go#L560-L596","documentation":"ReinitWithKey stops the current device and builds a replacement from the supplied private key bytes via core.NewDevice; if construction fails it returns this error before swapping anything in. It is used by runRegisterApp after generating a fresh key pair for registration.","triggerScenarios":"Calling ReinitWithKey (from runRegisterApp) with privKeyBytes that core.NewDevice cannot accept — nil slice, wrong length, or otherwise invalid key material.","commonSituations":"Key-generation step upstream returned empty/short bytes; passing a base64 string's bytes instead of decoded key bytes; cipher-scheme mismatch.","solutions":["Ensure the key came from a successful keygen/curve25519 generation (32 decoded bytes), and pass the decoded bytes, not the base64 string bytes","Check the code path that generated privKeyBytes for an ignored error or empty result","Log the byte length of privKeyBytes before calling ReinitWithKey to confirm validity"],"exampleFix":"// before\na.ReinitWithKey([]byte(privKeyB64), cipherScheme)\n// after\nprk, err := base64.StdEncoding.DecodeString(privKeyB64)\nif err != nil { return err }\na.ReinitWithKey(prk, cipherScheme)","handlingStrategy":"validation","validationCode":"if len(privKeyBytes) != 32 {\n    return fmt.Errorf(\"ReinitWithKey: expected 32-byte key, got %d\", len(privKeyBytes))\n}","typeGuard":null,"tryCatchPattern":"if err := a.ReinitWithKey(prk, cipherScheme); err != nil {\n    log.Fatalf(\"new device from registration key failed: %v\", err)\n}","preventionTips":["Check the error from the key-generation call before using its output","Pass decoded bytes, never base64 string bytes","Assert key length before device creation"],"tags":["go","crypto","registration"],"backgroundTag":"invalid-constructor-argument","analyzedSha":"6e04ca5ff03222a699c24205cd4bf8fee9af7ffe","analyzedAt":"2026-09-07T15:44:59.941Z","contentChangedAt":"2026-09-07T15:44:59.941Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}