808bits

CKR_OPERATION_NOT_INITIALIZED

PKCS#11 return value · 0x00000091 · decimal 145
hex 0x00000091 decimal 145 name CKR_OPERATION_NOT_INITIALIZED

Multi-part operations are state on the session, and this code says the session held none of the kind you asked for. The plain case is a missing Init. The ones that get reported are an Init whose failure went unchecked, an operation the library quietly cancelled after an earlier error, and two threads taking turns on one session so that one thread's Final lands after the other's has consumed the state.

What the token is reporting

The session has no active operation of the type this call belongs to. A sign needs a sign initialisation on the same session that has not since been consumed, cancelled or replaced.

Likely causes

Ordered by how often they turn out to be the answer. That ordering is a judgement from experience, not a measured frequency.

The Init failed and the code went on

The initialisation returned a mechanism, key or parameter error, the caller did not check it, and the next call found no operation. The code you are reading is then the second error, and the first one is the real one.

Check it: Check the return value of the initialisation call on that session. If it was anything but success, this code is a consequence.

The operation was consumed or reset by an earlier call

A successful single-part call ends the operation, so a second sign without a second initialisation gets this code. Many failures also reset the operation: a buffer too small usually leaves it in place, but a bad data length or a failed update clears it on most libraries, and the next call reports the missing state rather than the original problem.

Check it: Look at the previous return code on the same session. A failure there that is not buffer too small will have cleared the operation.

Two threads sharing a session

A session carries one active operation per kind, and libraries do not partition it per thread. Thread A initialises, thread B initialises or finishes, and thread A’s final call finds nothing or finds B’s state. The failure is intermittent and load-dependent, which is the tell.

Check it: Log the session handle and thread id on every call. Any session that appears under two thread ids is the answer.

Fix: One session per thread, or a session pool with exclusive checkout.

A context-specific login with nothing pending

Logging in with the context-specific user type is only valid while an operation that requires it is in progress, on a key marked as always authenticate. Called at any other time, several libraries answer with this code from the login call itself, which is not where anyone looks for it.

Check it: If the failing call is a login, check the user type and whether a signing operation was initialised on that session just before.

Which calls return it

C_Sign, C_SignUpdate, C_SignFinal, C_Encrypt, C_Decrypt, C_Digest, C_FindObjects, C_Login

What it is not

It is not the library being uninitialised, which is the cryptoki variant and fails every call. It is not a session problem either. The handle is valid, it just holds no operation.

Often confused with

  • CKR_OPERATION_ACTIVE: The mirror image. That code means an operation is already in progress when you tried to start another. Both come from the same shared-session mistake.
  • CKR_CRYPTOKI_NOT_INITIALIZED: The library-level version. Every call fails, not just the ones that need an operation.
  • CKR_SESSION_HANDLE_INVALID: When the session itself is gone, the state went with it, and which of the two you see depends on which check the library runs first.

By library

SoftHSMv2

Every single-part and multi-part call checks for its operation, and C_FindObjects without a find initialisation gets the same code. A failed update resets the operation, so the call after a data length failure reports this rather than the length. The login call returns it for a context-specific login with no re-authentication pending (SoftHS M.cpp).

OpenSC

One helper looks up the session’s operation for every call ([misc.c](h ttps://github.com/OpenSC/OpenSC/blob/4fab8b57301f035432191d582922d95d7d 426802/src/pkcs11/misc.c#L286-L310)), and the login call returns it for a context-specific login when nobody is logged in ([pkcs11-session.c](h ttps://github.com/OpenSC/OpenSC/blob/4fab8b57301f035432191d582922d95d7d 426802/src/pkcs11/pkcs11-session.c#L359-L362)).

YubiHSM 2

Comes from the sign and verify paths, single and multi-part. The other operation families report missing state through their own checks.

Thales Luna

Six native codes map to it, and they include M of N activation required and the high availability user not being initialised. On a Luna this code can mean the partition is not activated, which has nothing to do with your initialisation call. The client log has the native code.

Sources

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.