Skip to content

Token Serial Not Reported By The Declared Backend

URI: https://docs.ankatech.co/errors/token-serial-not-reported
HTTP Status: 409 Conflict

When you see this

The deployment would end up selecting its PKCS#11 token by serial (PKCS11_TOKEN_SELECT_BY=serial) while its key-protection backend — the one declared, or the one configured and not yet declared — is a backend whose PKCS#11 module reports no token serial. AWS CloudHSM is that backend: its module answers C_GetTokenInfo with an empty serial number (the token URI reads serial=;token=hsm1), so a selection by serial could never address its token. The refusal is made when either side is written, instead of surfacing later at the bind as a token the module does not present.

Four writers can bring the two sides together, and each answers this type before it writes anything:

Request Refused when
PUT /api/v3/admin/platform/settings/PKCS11_TOKEN_SELECT_BY the value is serial and the declared or configured backend reports no token serial
DELETE /api/v3/admin/platform/settings/PKCS11_TOKEN_SELECT_BY removing the override would make the selection fall back to serial on such a backend
PUT /api/v3/admin/platform/setup/backend/configuration the backend being configured reports no token serial while PKCS11_TOKEN_SELECT_BY is serial
POST /api/v3/admin/platform/setup/backend/declare the backend being declared reports no token serial while PKCS11_TOKEN_SELECT_BY is serial. Only a change of declaration is judged: re-declaring the backend already declared declares nothing new and is not refused
POST /api/v3/admin/platform/setup/backend/activate the backend being activated reports no token serial while PKCS11_TOKEN_SELECT_BY is serial. Judged before the backend is contacted: nothing is contacted and no key is created

Because every writer of either side is judged, the state cannot arise while an activation runs: while such a backend is configured a serial selection cannot be written, and while the selection is serial such a backend cannot be configured. The activation therefore does not judge again when it records its result.

What is not refused:

  • No backend declared or configured yet. There is no vendor to judge against, so serial is accepted; the configuration or declaration that follows is refused instead if the selection is still serial then.
  • Backends whose module reports a serial — SoftHSM, Thales Luna, Entrust nShield — and every Cloud KMS backend, which selects no PKCS#11 token at all. Either selection is accepted on them.
  • A PKCS11_TOKEN_SERIAL value on its own. The serial coordinate is read only when the token is selected by serial, which this rule refuses, so writing it changes nothing and is accepted.

This is a 409 rather than a 400 because each value is valid on its own — serial is one of the values the setting accepts, and cloudhsm is a backend the deployment may offer — and they conflict only with each other, in the current state of the deployment. It is resolved by acting on that state (RFC 9110 §15.5.10).

Common Causes

  • PKCS11_TOKEN_SELECT_BY was set to serial through the API or the CLI on a deployment that declares or has configured AWS CloudHSM.
  • The selector was set to serial before any backend was configured or declared, and AWS CloudHSM is now being configured, declared or activated.
  • The selector override was removed on a CloudHSM deployment whose fallback value — the value the setting resolves to without an override — is serial.

Response Example

{
  "type": "https://docs.ankatech.co/errors/token-serial-not-reported",
  "title": "Token Serial Not Reported By The Declared Backend",
  "status": 409,
  "detail": "The key-protection backend 'cloudhsm', declared or configured on this deployment, reports no PKCS#11 token serial, so PKCS11_TOKEN_SELECT_BY=serial could never address its token. Select the token by label: in the Admin Console, Platform Settings > Cryptography & Trust > HSM / Cloud KMS, keep the token selection PKCS11_TOKEN_SELECT_BY on label and set PKCS11_TOKEN_LABEL to the label the token reports (API: PUT /api/v3/admin/platform/settings/PKCS11_TOKEN_LABEL). Nothing was changed.",
  "instance": "/api/v3/admin/platform/settings/PKCS11_TOKEN_SELECT_BY",
  "timestamp": 1787494020,
  "extensions": {
    "requestId": "4f1c2a7e-8b39-4d06-a5e2-7c9d0b3f6a18"
  }
}

Content-Type: application/problem+json — the response follows RFC 9457 Problem Details.

The detail names the backend in its canonical lowercase form, the setting names, the console screen where the selection is changed and the API path that changes it — never a submitted value, a token label or a serial. On the configuration, the declaration and the activation the detail reads the other way round — the backend being configured, declared or activated reports no serial, and the selection must be set to label first — and its instance is that operation's path (/api/v3/admin/platform/setup/backend/configuration, /api/v3/admin/platform/setup/backend/declare or /api/v3/admin/platform/setup/backend/activate).

What this refusal leaves behind. Nothing on the platform: a refused settings write or configuration persists, publishes and audits nothing, a refused declaration records no declaration and derives no descriptor, and a refused activation contacts no backend and creates no key.

On the environment host

When the host activation (init-hsm.sh <env> --activate) delegates to POST /api/v3/admin/platform/setup/backend/activate and receives this refusal, it prints the platform's detail, states that the host wrote no .env bind and that the platform refused before contacting the backend, and exits 4 — the coordinate-refusal code. That message also says it is not "nothing was written": if --pkcs11-pin-file was supplied, the partition credential was installed before the delegation, so the environment's PIN secret and its disaster-recovery copy already hold the new value. Select the token by label as below, then run --activate again.

Knowing before you write

The settings row for PKCS11_TOKEN_SELECT_BY lists the refused value before any write is attempted. Wherever that row is returned — GET /api/v3/admin/platform/settings/PKCS11_TOKEN_SELECT_BY, GET /api/v3/admin/platform/settings/catalog, GET /api/v3/admin/platform/settings/overrides and the PUT response — it carries an inadmissibleValues array whose entry names the value, the reason and the backend:

"inadmissibleValues": [
  {
    "value": "serial",
    "reason": "TOKEN_SERIAL_NOT_REPORTED",
    "backend": "cloudhsm"
  }
]

backend is always present on an entry and names the declared backend, or the one configured for activation while none is declared. The member is absent when no value is refused — on every other setting, and on this one whenever the backend in play reports a serial or none is declared or configured. The console offers only the admissible values and states the reason beside the selector.

How to Resolve

  1. Select the token by label: in the Admin Console, Platform Settings → Cryptography & Trust → HSM / Cloud KMS, set PKCS11_TOKEN_SELECT_BY to label and PKCS11_TOKEN_LABEL to the label the token reports (on AWS CloudHSM under Client SDK 5, hsm1; read it off your cluster with pkcs11-tool -T). Through the API, PUT /api/v3/admin/platform/settings/PKCS11_TOKEN_SELECT_BY and PUT /api/v3/admin/platform/settings/PKCS11_TOKEN_LABEL.
  2. If the refusal came from the configuration, the declaration or the activation, run it again once the selection is label.
  3. If the refusal came from removing the override, keep an explicit label override instead of removing it.

For full schema definitions, examples, and interactive testing, see the Developer Hub Reference.