CKR_OPERATION_ACTIVE
A session holds at most one active operation of each kind, and this code means you tried to start a second before the first was finished or cancelled. Almost every report is one of two things: a multi-part operation abandoned after an error without the final call that would have closed it, or two threads taking turns on one session. It is easier to run down than most codes because the fix is always about the session and never about the key or the mechanism.
What the token is reporting
The session already has an operation of the type you are initialising. The new one was not started, and the old one is still in place.Likely causes
Ordered by how often they turn out to be the answer. That ordering is a judgement from experience, not a measured frequency.
A multi-part operation abandoned after an error
An update failed, the caller moved on, and the next initialisation of the same kind on that session finds the old operation still open. In the 2.x interface there is no cancel call, so the leftover survives until something finishes it or the session closes.Check it: Log the last operation started on the session. If it never reached a final call, this is it.
Fix: On any error in a multi-part operation, either finish it with a final call whose result you discard, close the session, or on a 3.0 library use the session cancel call.
Two threads sharing a session
Libraries do not partition a session’s state per thread. Two threads initialising sign operations on one session collide, and which one gets this code depends on timing. It shows up under load and not in tests.Check it: Log session handle and thread id on every call. A session seen from two threads is the answer.
Fix: A session per thread, or a pool with exclusive checkout.
A find that was never finalised
A search is an operation too. A secondC_FindObjectsInit without a C_FindObjectsFinal in between gets this code, and tooling that returns early from a search loop leaves the find open.Check it: Pair every find initialisation with a final in the trace.
Which calls return it
C_EncryptInit, C_DecryptInit, C_DigestInit, C_SignInit, C_VerifyInit, C_FindObjectsInit
What it is not
It is not a lock, not a busy token and not a device state. Nothing about the hardware is involved. The session in this process is holding state and that is all.Often confused with
CKR_OPERATION_NOT_INITIALIZED: The mirror. Both come from the same shared-session and abandoned- operation mistakes, and which one you see depends on which thread ran first.CKR_SESSION_HANDLE_INVALID: Closing the session is one way to clear the leftover operation, and a handle kept past that point turns into this instead.
By library
SoftHSMv2
Every initialisation checks the session’s operation slot for its kind, including the digest, MAC, asymmetric and recover variants (SoftHSM.c pp).OpenSC
A single helper starts every operation and refuses when one of that type already exists on the session (misc.c).YubiHSM 2
Also returned from key pair generation, wrap and unwrap when an operation is in progress on the session, so a YubiHSM refuses to generate or wrap in the middle of a multi-part operation, which the specification does not require.Sources
- PKCS #11 Specification Version 3.2, OASIS. Read 2026-09-10. Used for constant name and numeric value.
Every description, cause and check on this page is written from scratch. The specification is cited for the constant's name and its number, which are facts, and for nothing else.