{"record":{"id":"3be4c41ef2a9bf04","repo":"OpenNHP/opennhp","slug":"failed-to-create-device-v-3be4c4","errorCode":null,"errorMessage":"failed to create device %v","messagePattern":"failed to create device (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"endpoints/agent/udpagent.go","lineNumber":399,"sourceCode":"\t\t// real misconfiguration — fail loudly instead of silently starting\n\t\t// with a random key and empty identity.\n\t\tif !a.allowMissingConfig {\n\t\t\tlog.Error(\"no private key configured in etc/config.toml\")\n\t\t\treturn fmt.Errorf(\"no private key configured; check etc/config.toml\")\n\t\t}\n\t\tprk = core.NewECDH(core.ECC_CURVE25519).PrivateKey()\n\t} else {\n\t\tprk, err = base64.StdEncoding.DecodeString(a.config.PrivateKeyBase64)\n\t\tif err != nil {\n\t\t\tlog.Error(\"private key parse error %v\\n\", err)\n\t\t\treturn fmt.Errorf(\"private key parse error %v\", err)\n\t\t}\n\t}\n\n\ta.device = core.NewDevice(core.NHP_AGENT, prk, nil)\n\tif a.device == nil {\n\t\tlog.Critical(\"failed to create device %v\\n\", err)\n\t\treturn fmt.Errorf(\"failed to create device %v\", err)\n\t}\n\n\t// start device routines\n\ta.device.Start()\n\n\t// serverClusterMap must be non-nil before loadPeers runs (so\n\t// updateServerPeers' map-swap has a base value) and before\n\t// callers like AddServer / GetFirstServerPeer touch it on\n\t// agents that haven't loaded a server.toml yet.\n\ta.serverClusterMap = make(map[string]*ServerCluster)\n\ta.serverClusterByName = make(map[string]*ServerCluster)\n\n\t// load peers\n\t_ = a.loadPeers()\n\n\ta.remoteConnectionMap = make(map[string]*UdpConn)\n\n\ta.signals.stop = make(chan struct{})","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/endpoints/agent/udpagent.go#L381-L417","documentation":"After decoding the private key, Start calls core.NewDevice(NHP_AGENT, prk, nil); if that returns nil the agent cannot build its device (ECDH context / device identity) and Start fails. This wraps an internal device-construction failure, typically from invalid key length or cipher/crypto initialization.","triggerScenarios":"Start with a private key that decodes from base64 but has an invalid byte length or otherwise fails ECDH initialization inside core.NewDevice.","commonSituations":"Truncated key from a partial copy-paste; key generated for a different cipher scheme with wrong byte size; corrupted key file.","solutions":["Regenerate a fresh key pair with keygen --curve and use it","Verify the decoded key is 32 bytes (curve25519)","Check agent/server logs (log.Critical line) and the nhp/core NewDevice code for the exact nil-return condition"],"exampleFix":"// before\nprk = []byte(\"shortkey\")\n// after\nprk, _ := base64.StdEncoding.DecodeString(\"<32-byte base64 key from keygen>\")","handlingStrategy":"try-catch","validationCode":"prk, err := base64.StdEncoding.DecodeString(cfg.PrivateKeyBase64)\nif err != nil || len(prk) != 32 {\n    return fmt.Errorf(\"agent key must decode to 32 bytes, got %d\", len(prk))\n}","typeGuard":null,"tryCatchPattern":"if err := agent.Start(); err != nil {\n    if strings.Contains(err.Error(), \"failed to create device\") {\n        log.Fatalf(\"device init failed (%v); regenerate key with keygen --curve\", err)\n    }\n}","preventionTips":["Validate decoded key length is 32 bytes before Start","Regenerate keys with the bundled keygen tool rather than external tools","Keep agent and core library versions aligned"],"tags":["go","crypto","device-init"],"backgroundTag":"module-init-failed","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"}