{"record":{"id":"858c1352c0ff303d","repo":"OpenNHP/opennhp","slug":"failed-to-create-device-v","errorCode":null,"errorMessage":"failed to create device %v","messagePattern":"failed to create device (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"endpoints/ac/udpac.go","lineNumber":142,"sourceCode":"\t\terr = ebpflocal.EbpfEngineLoad(dirPath, logLevel, a.config.ACId)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\tdefault:\n\t\tlog.Error(\"[HandleAccessControl] unsupported FilterMode: %d (expected 0=IPTABLES or 1=EBPFXDP)\", a.config.FilterMode)\n\t\treturn\n\t}\n\n\tprk, err := base64.StdEncoding.DecodeString(a.config.PrivateKeyBase64)\n\tif err != nil {\n\t\tlog.Error(\"private key parse error %v\\n\", err)\n\t\treturn fmt.Errorf(\"private key parse error %v\", err)\n\t}\n\n\ta.device = core.NewDevice(core.NHP_AC, 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\ta.remoteConnectionMap = make(map[string]*UdpConn)\n\ta.serverPeerMap = make(map[string]*core.UdpPeer)\n\ta.tokenStore = common.NewTokenStore[*AccessEntry]()\n\n\tif a.etcdConn != nil {\n\t\t_ = a.loadRemoteConfig()\n\t} else {\n\t\t// load http config and turn on http server if needed\n\t\t_ = a.loadHttpConfig()\n\n\t\t// load peers. A non-nil error here means the initial\n\t\t// expandServerPeers parse failed and the running peerMap is\n\t\t// empty. Starting the daemon in that state lets it drop\n\t\t// AOL/AOP traffic silently (no peer matches), which is much\n\t\t// harder to diagnose than a startup refusal. Reloads still\n\t\t// keep the previous peer table on parse error — that's the","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/endpoints/ac/udpac.go#L124-L160","documentation":"UdpAC.Start returns \"failed to create device %v\" when core.NewDevice(core.NHP_AC, prk, nil) returns nil after the private key successfully base64-decodes. NewDevice validates the key material for the device type and cipher scheme; nil means the decoded bytes are not a usable private key.","triggerScenarios":"PrivateKeyBase64 decodes as base64 but its byte length is wrong for the scheme (e.g. 32-byte curve key configured while GMSM/SM2 scheme selected, or truncated/garbage bytes); NewDevice's internal key generation/validation fails and returns nil.","commonSituations":"Rotating keys between curve25519 and SM2 without regenerating; provisioning scripts truncating the base64 string; copying a public key into the private-key field.","solutions":["Regenerate a matching keypair with `./nhp-acd keygen --curve` (or --sm2) and update config.toml","Verify the key byte length matches the cipher scheme selected in config","Ensure the value is the private key, not the public key, and of the same scheme as peers expect","Improve NewDevice to return an error describing why the key was rejected instead of nil"],"exampleFix":"// before\na.device = core.NewDevice(core.NHP_AC, prk, nil)\nif a.device == nil {\n\treturn fmt.Errorf(\"failed to create device %v\", err)\n}\n// after\na.device = core.NewDevice(core.NHP_AC, prk, nil)\nif a.device == nil {\n\treturn fmt.Errorf(\"failed to create device: invalid %d-byte private key for selected cipher scheme\", len(prk))\n}","handlingStrategy":"validation","validationCode":"prk, err := base64.StdEncoding.DecodeString(conf.PrivateKeyBase64)\nif err != nil { return err }\nif len(prk) != 32 { // curve25519 expected size\n\treturn fmt.Errorf(\"private key is %d bytes, expected 32\", len(prk))\n}","typeGuard":null,"tryCatchPattern":"a.device = core.NewDevice(core.NHP_AC, prk, nil)\nif a.device == nil {\n\treturn fmt.Errorf(\"device creation failed: check key length/scheme (got %d bytes)\", len(prk))\n}","preventionTips":["Match key scheme (curve vs SM2) to the configured cipher scheme","Never reuse public keys in the private-key field","Regenerate keypairs after scheme changes"],"tags":["crypto","device","config","startup"],"backgroundTag":"invalid-config-value","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"}