{"record":{"id":"4cb8044d10712494","repo":"OpenNHP/opennhp","slug":"failed-to-create-device-v-4cb804","errorCode":null,"errorMessage":"failed to create device %v","messagePattern":"failed to create device (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"endpoints/server/udpserver.go","lineNumber":275,"sourceCode":"\ts.listenAddr, err = net.ResolveUDPAddr(laddr.Network(), laddr.String())\n\tif err != nil {\n\t\tlog.Error(\"resolve local UDPAddr error: %v\", err)\n\t\treturn fmt.Errorf(\"resolve UDPAddr error %v\", err)\n\t}\n\n\tprk, err := base64.StdEncoding.DecodeString(s.config.PrivateKeyBase64)\n\tif err != nil {\n\t\tlog.Error(\"private key parse error: %v\", err)\n\t\treturn fmt.Errorf(\"private key parse error %v\", err)\n\t}\n\n\toption := &core.DeviceOptions{\n\t\tDisableAgentPeerValidation: s.config.DisableAgentValidation,\n\t}\n\ts.device = core.NewDevice(core.NHP_SERVER, prk, option)\n\tif s.device == nil {\n\t\tlog.Critical(\"failed to create device: %v\", err)\n\t\treturn fmt.Errorf(\"failed to create device %v\", err)\n\t}\n\n\t// Stateless cookie signing key. In a multi-instance cluster all\n\t// nhp-server replicas must share the same value so any of them can\n\t// verify a cookie that a sibling minted. When the operator hasn't\n\t// configured one we mint a random per-process key — fine for a single\n\t// instance, broken for a cluster (the failure is silent: cookies\n\t// minted by replica A don't verify on replica B and the agent's RKN\n\t// stalls until timeout). Always log which mode we're in.\n\tcookieKey, cookieKeyErr := decodeCookieSigningKey(s.config.CookieSigningKeyBase64)\n\tif cookieKeyErr != nil {\n\t\t// Malformed (not empty) is an ops mistake — fail fast rather\n\t\t// than silently degrading to a per-process random key. Silent\n\t\t// fallback would let a cluster look healthy while its replicas\n\t\t// each mint cookies a sibling can't verify.\n\t\tlog.Critical(\"invalid CookieSigningKeyBase64 in config: %v\", cookieKeyErr)\n\t\treturn fmt.Errorf(\"invalid CookieSigningKeyBase64: %w\", cookieKeyErr)\n\t}","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/endpoints/server/udpserver.go#L257-L293","documentation":"core.NewDevice(NHP_SERVER, prk, option) returned nil, meaning the core device could not be initialized from the decoded private key, so Start fails with this error. The log also prints the accompanying err (which may be nil if NewDevice fails silently on an invalid key).","triggerScenarios":"The base64-decoded private key has the wrong length or is invalid for the selected cipher scheme (e.g. not a 32-byte Curve25519/SM2 key), or the key is all zeros/rejected by validation.","commonSituations":"Truncated key from a copy-paste; key generated for a different cipher scheme than the peers expect; empty key after failed decode handled earlier but of wrong size.","solutions":["Regenerate a fresh key pair with nhp-serverd keygen and redeploy the private key","Verify the decoded key length matches the cipher scheme requirement (32 bytes for curve25519)","Check for err being nil in the log line — if so the key bytes are structurally invalid","Ensure the key was not base64-decoded twice or truncated during templating"],"exampleFix":"// before\nprk = short/truncated base64 -> decoded 12 bytes\n// after\nnhp-serverd keygen --curve --json  # then copy privateKeyBase64 exactly","handlingStrategy":"validation","validationCode":"key, err := base64.StdEncoding.DecodeString(cfg.PrivateKeyBase64)\nif err != nil || len(key) != 32 {\n    return fmt.Errorf(\"device key must decode to 32 bytes, got %d (err=%v)\", len(key), err)\n}","typeGuard":null,"tryCatchPattern":"if err := server.Start(); err != nil {\n    if strings.Contains(err.Error(), \"failed to create device\") {\n        return fmt.Errorf(\"regenerate server keys with 'keygen' and redeploy: %w\", err)\n    }\n    return err\n}","preventionTips":["Regenerate keys with keygen when device init fails","Verify decoded key length matches the cipher scheme","Never truncate or re-encode keys during config templating"],"tags":["device","init","key","startup"],"backgroundTag":"invalid-argument-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"}