{"record":{"id":"be3359f62f937dc4","repo":"slackhq/nebula","slug":"failed-to-open-session-on-slot-d","errorCode":null,"errorMessage":"failed to open session on slot %d","messagePattern":"failed to open session on slot (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkclient/pkclient_cgo.go","lineNumber":60,"sourceCode":"\t// Try to open a session on the slot\n\tslotIdx := 0\n\tfor i, slot := range slots {\n\t\tif slot.ID() == slotId {\n\t\t\tslotIdx = i\n\t\t\tbreak\n\t\t}\n\t}\n\n\tclient := &PKClient{\n\t\tmodule: module,\n\t\tid:     []byte(id),\n\t\tlabel:  []byte(label),\n\t}\n\n\tclient.session, err = slots[slotIdx].OpenWriteSession()\n\tif err != nil {\n\t\tmodule.Destroy()\n\t\treturn nil, fmt.Errorf(\"failed to open session on slot %d\", slotId)\n\t}\n\n\tif len(pin) != 0 {\n\t\terr = client.session.Login(pin)\n\t\tif err != nil {\n\t\t\t// ignore \"already logged in\"\n\t\t\tif !errors.Is(err, pkcs11.Error(256)) {\n\t\t\t\t_ = client.session.Close()\n\t\t\t\treturn nil, fmt.Errorf(\"unable to login. error: %w\", err)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Make sure the hsm has a private key for deriving\n\tclient.privKeyObj, err = client.findDeriveKey(client.id, client.label, true)\n\tif err != nil {\n\t\t_ = client.Close() //log out, close session, destroy module\n\t\treturn nil, fmt.Errorf(\"failed to find private key for deriving: %w\", err)","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/pkclient/pkclient_cgo.go#L42-L78","documentation":"New() opened a read-write session on the selected slot but OpenWriteSession failed, so the module is destroyed and this message (without the underlying cause) is returned. The library throws it because writing/deriving operations require a session and the token refused to open one.","triggerScenarios":"Calling New() when slots[slotIdx].OpenWriteSession() errors: slot is busy/exclusive, token not present, serial sessions exhausted, or user PIN blocks write sessions.","commonSituations":"Another process holds the only session (HSM max-session limit); wrong slotId so the chosen slot has no token; HSM in a bad state requiring reinsertion; vendor middleware misconfigured.","solutions":["Verify slotId matches a token-present slot (pkcs11-tool --list-slots)","Close other processes/sessions holding the HSM and retry","Restart the HSM/middleware daemon (e.g. pcscd) if the token is wedged","Check vendor max-session limits and free sessions","Re-plug/reseat the token or reset it if the slot is unresponsive"],"exampleFix":"// before\npkcs11_slot: 5\n// after (pick a slot with a token)\n# pkcs11-tool --list-slots\npkcs11_slot: 0","handlingStrategy":"retry","validationCode":"// pick a slot that actually has a token before New()\nctx := pkcs11.New(modulePath); ctx.Initialize()\nslots, _ := ctx.GetSlotList(true)\nfor _, s := range slots {\n    info, err := ctx.GetTokenInfo(s)\n    if err == nil { fmt.Println(s, info.Label) } // choose one with a token\n}","typeGuard":null,"tryCatchPattern":"client, err := pkclient.New(hsmPath, slot, pin, id, label)\nif err != nil && strings.Contains(err.Error(), \"failed to open session\") {\n    time.Sleep(2 * time.Second) // let other holders release sessions, then retry\n    return pkclient.New(hsmPath, slot, pin, id, label)\n}","preventionTips":["Verify slotId with pkcs11-tool --list-slots","Limit concurrent processes holding HSM sessions","Restart pcscd/middleware if the token is wedged","Know the token's max-session limit"],"tags":["pkcs11","hsm","session","slot"],"backgroundTag":"pkcs11-open-session-failed","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}