1. guides
prorm
  • prorm documentation
  • Known test gaps
  • Architecture
  • Core concepts
  • Database types & coverage
  • Getting started
  • Going further
  • compliance
    • Compliance
    • The security toolkit: `prorm audit`
    • Checklists by regulation
    • Declaring personal data
    • Evidence bundles
    • Evidence
    • Frameworks: `@Security`
    • Jurisdictions
    • Platform policies
    • Protecting data
    • The regulation dataset
    • Residency and cross-border transfers
    • Retention & integrity
    • Status
    • Subject rights
  • decorators
    • prorm with decorators
    • Models with decorators
    • Querying a decorated model
    • Relations with decorators
  • diagrams
    • Diagram generators
    • Chen diagram
    • Class diagram
    • Dependency diagram
    • ER diagram
    • Flow diagram
    • From your models to a diagram
    • Gantt diagram
    • Index diagram
    • Migration diagram
    • Model diagram
    • Package diagram
    • Crow’s-foot diagram
    • Schema documentation
    • Sequence diagram
    • State diagram
    • Tree diagram
  • dialects
    • SQL dialects
    • AlloyDB Dialect
    • AlloyDB Omni Dialect
    • Amazon Athena Dialect
    • Aurora DSQL Dialect
    • Amazon Aurora MySQL Dialect
    • Amazon Aurora PostgreSQL Dialect
    • Azure Database for MySQL Dialect
    • Azure Database for PostgreSQL Dialect
    • Azure SQL Database Dialect
    • Azure SQL Managed Instance Dialect
    • Google BigQuery Dialect
    • Citus Dialect
    • ClickHouse dialect
    • Cloud Authentication (`cloud-auth`)
    • Cloud SQL for SQL Server Dialect
    • Cloud SQL for MySQL Dialect
    • Cloud SQL for PostgreSQL Dialect
    • CockroachDB Dialect
    • Azure Cosmos DB for PostgreSQL Dialect
    • CrateDB Dialect
    • Cloudflare D1 Dialect
    • Databricks dialect
    • IBM Db2 Dialect
    • Dolt Dialect
    • Apache Doris Dialect
    • Druid Dialect
    • DuckDB Dialect
    • Exasol dialect
    • Microsoft Fabric Data Warehouse Dialect
    • Firebird Dialect
    • Greenplum Dialect
    • SAP HANA Dialect
    • MySQL HeatWave Dialect
    • Azure Data Explorer (Kusto) Dialect — T-SQL
    • MariaDB Dialect
    • Materialize Dialect
    • MonetDB Dialect
    • MotherDuck Dialect
    • Microsoft SQL Server Dialect
    • MySQL Dialect
    • Neon Dialect
    • OceanBase Dialect
    • openGauss Dialect
    • Oracle Dialect
    • Oracle Autonomous Database Dialect
    • ParadeDB Dialect
    • PolarDB Dialect
    • PostgreSQL Dialect
    • Presto Dialect
    • QuestDB Dialect
    • Aurora RDS Data API Dialect (`rdsdata`)
    • Amazon RDS for Db2 Dialect
    • Amazon RDS for MariaDB Dialect
    • Amazon RDS for SQL Server Dialect
    • Amazon RDS for MySQL Dialect
    • Amazon RDS for Oracle Dialect
    • Amazon RDS for PostgreSQL Dialect
    • Amazon Redshift
    • Amazon Redshift Data API Dialect
    • RisingWave Dialect
    • rqlite Dialect
    • SingleStore Dialect
    • Snowflake Dialect
    • Google Cloud Spanner Dialect
    • Spanner (PostgreSQL interface) Dialect
    • SQLite Dialect
    • StarRocks Dialect
    • Supabase Dialect
    • Azure Synapse Analytics (dedicated SQL pool)
    • Teradata Dialect
    • TiDB Dialect
    • TimescaleDB Dialect
    • Trino Dialect
    • Turso / libSQL Dialect
    • Vertica dialect
    • Vitess Dialect
    • Yellowbrick Dialect
    • YugabyteDB Dialect
  • guides
    • Access rules and behaviour profiles
    • ArangoDB (AQL)
    • Associations
    • Audit levels and escalation
    • Audit logging
    • In the browser
    • Bulk operations
    • Caching
    • Capabilities, tiers and team roles
    • CLI
    • Cloudflare
    • Compliance & data protection
    • Connection Pooling & Performance
    • Security in the console
    • Couchbase: structured N1QL queries
    • Data types
    • Decorators
    • Eager loading
    • Enums and constants
    • Error handling & error types
    • Extensions
    • External fields
    • Foreign data wrappers
    • Graph databases
    • Hooks & lifecycle events
    • Indexes & constraints
    • InfluxDB: structured Flux pipelines
    • klock-errors
    • klock — the `.klock` file
    • Local databases (`prorm db up`)
    • Structured log search — Splunk, Graylog, Papertrail, Sumo Logic
    • Logging
    • Grafana Loki: structured LogQL queries
    • MCP server
    • Migrate — the data transfer subsystem
    • Migrations & Schema Sync
    • Models from an existing database
    • Defining models
    • Multiple databases
    • OrientDB, Neptune and TigerGraph
    • Passwords
    • Importing a Prisma schema
    • Structured PromQL and MetricsQL
    • Query firewall
    • QueryInterface
    • Query operators reference
    • Query optimization
    • Composing find options with `pipe()` and `Q`
    • Query safety: the fail-closed WHERE guard
    • Querying
    • Raw Queries & Query Building
    • Read replicas
    • Schema diffing & migration generation
    • Views, triggers & other schema objects
    • Scopes & default scopes
    • Seeders
    • SPARQL / RDF triplestores
    • SQL constants
    • SQL features
    • SQL function builders
    • SQLite advanced features
    • StoreKey — a prod-orm database as the storage
    • Streaming results
    • Terraform
    • Transactions & Isolation Levels
    • Type mapping: legacy and modern
    • TypeScript types
    • Database users, roles & privileges
    • Validation & constraints
    • Virtual & Computed Fields
    • Writing docs
  • javascript
    • prorm in JavaScript
    • Models in JavaScript
    • Querying in JavaScript
    • Relations in JavaScript
  • runbooks
    • Operational runbooks
    • Connection failures
    • Credential rotation
    • Failover
    • Incident checklist
    • Deploying klock v2
    • Migration rollback
  • running-databases
    • Running databases in Docker
    • Running prorm under Bun in Docker
    • Running Cassandra in Docker with prorm
    • Running ClickHouse in Docker with prorm
    • Running CockroachDB in Docker with prorm
    • Running prorm under Deno in Docker
    • Running Elasticsearch in Docker with prorm
    • Running MariaDB in Docker with prorm
    • Running MongoDB in Docker with prorm
  • prorm control plane
    • Introduction
    • Authentication
    • Errors
    • Getting started
      • Service
        • Is it up
        • This description
    • Account
      • Sign-up and verification
        • Create an account
        • Exchange credentials for a token
        • Verify with the emailed code
        • Verify by clicking the emailed link
        • Name the parent or guardian
        • What a consent link is about
        • Give consent for a child's account
        • Ask the parent or guardian again
        • Send a new code and link
      • Family
        • Everyone this account is responsible for
        • One child, in detail
        • Turn a limit on or off
      • Profile
        • Who am I
        • Change the account
        • Every address on the account
        • Add an address
        • Confirm an address with the code mailed to it
        • Mail a fresh code to an unconfirmed address
        • Make an address primary
        • Remove an address
        • What this caller may do
    • Security
      • Sessions
        • Everywhere this account is signed in
        • Sign out everywhere else
        • Sign one out
        • A token for the CLI on a named machine
        • A token for the customer console, from the staff one
        • Park a sign-in for the CLI to collect
        • The CLI collecting its sign-in
        • The team's members' live sessions
        • Sign a member's session out
        • Sign an account out everywhere
        • Everywhere the account is signed in
        • Sign an account's session out
      • Single sign-on
        • Begin a single sign-on
        • The provider's return
        • Link the signed-in account to a team's provider
        • Which team an address signs in to
        • The team's single sign-on, as a member sees it
        • Set the team's OpenID Connect provider up, or change it
        • Remove the provider
        • The team's domain claims and the DNS record each needs
        • Prove a claimed domain
      • MFA and passwords
        • Start enrolling a second factor
        • Prove the app has it
        • Remove the second factor
        • Ask for a reset link
        • Set a new password with the emailed token
      • Klock
        • Open a device-bound klock session
        • Check in, for the next grant
        • Step up the session asking
        • Rotate the device key
        • Freeze a session
        • Unfreeze a session
        • A guest grant
        • The revocation feed
        • The published keyset
        • What this control plane supports
      • Devices
        • Your devices, or a team's
        • Approve a new device's pairing code
        • One device
        • Rename a device
        • Revoke a device
        • Suspend a device
        • Reinstate a suspended device
        • Wipe a device
        • Ask a device to rotate its key
        • The team's members' devices
        • Revoke a member's device
        • An account's devices
        • Revoke an account's device
        • Wipe an account's device
        • The device fleet
      • Access rules and behaviour
        • The access rules that bear on you
        • Add an access rule
        • This request, as the rules see it
        • One access rule
        • Remove an access rule
        • The behaviour profiles that bear on you
        • Add or change a behaviour profile
        • The profile presets
        • Your behaviour findings
        • Acknowledge a finding
        • One behaviour profile
        • Remove a behaviour profile
        • The team's access rules
        • Add a team access rule
        • Remove a team access rule
        • The team's behaviour profiles
        • Add or change a team behaviour profile
        • Remove a team behaviour profile
        • What the team's profiles caught
        • Acknowledge a team finding
      • Recovery and lockdown
        • Ask for a recovery link
        • Recover access with the emailed code
        • Is the account locked down
        • Lock the account down
        • Release a lockdown
        • Lock a member down
        • Release a member's lockdown
      • MCP tokens
        • Make a delegated token for one MCP client
        • The account's delegated tokens
        • Revoke a delegated token
        • What a delegated token may do now
        • Run one MCP tool with a delegated token
        • Run a device-signed MCP tool call relayed by the MCP Worker
      • Kerberos
        • Give the team its own Kerberos realm
        • The team's realm
        • Remove the team's realm
    • Logging and monitoring
      • Audit log
        • What has been done to the account
        • What has happened to this account
        • The account's audit trail
      • Operations
        • Everything that has been asked of this database
        • One, with its steps
        • Stop it
        • Put a failed one back in the queue
        • Every operation, across all accounts
      • Metrics and events
        • Every measurement, for a graph
        • Who did what to it
    • Billing
      • Plans and pricing
        • What the plans allow
        • The rate card
        • What one database would cost
        • What this account is paying for, itemised
      • Subscriptions and invoices
        • What this month's invoice will say
        • What this account is on
        • What it has been charged
        • Start a Stripe Checkout session
        • Open the customer portal
        • Stripe's events
        • Buy more connection pools
      • Team billing
        • The team's billing account
        • What the team has been charged
        • What this month's invoice will say
        • The team's cards
        • Add a card, through a Stripe-hosted setup session
        • Make a card the team's default
        • Remove a card
        • Start the team paying
        • Open the Stripe portal on the team's customer
        • Change the team's plan
        • Who receives the team's bills
        • How the team pays for transfers
    • Support
      • Support chat
        • My conversations
        • Start a conversation
        • Every support conversation, open first
        • A ticket for the socket
        • One conversation, with who is in it and who is connected
        • Rename a group; open or close a support conversation
        • The lines, oldest first
        • Say something
        • Add somebody
        • Mark read
    • Administration
      • Users
        • Every account
        • One account, with everything hanging off it
        • Grant or revoke admin
        • Verify an account by hand
        • Lock or unlock sign-in
        • Allow or hold provisioning
        • Send the verification mail again
        • Set the plan by hand
      • Platform
        • Every database and store, across all accounts
        • The counts worth putting on a dashboard
      • Staff and permissions
        • What kind of admin the caller is, and which scopes they hold
        • The admin presets
        • Every admin, and the scopes each resolves to
        • Make an account an admin of a kind
        • Change an admin's kind, or a custom admin's scopes
        • Revoke admin
      • Team administration
        • Every team, with its owner and size
        • One team in full — members with their accounts, and projects
        • Hand the team to another member
        • Put an account in the team, active at once
        • Change a member's role
        • Remove a member
      • Assumed identities
        • Assume an identity — act as a customer account
        • The identities the caller holds open
        • End an assumed identity
      • Support inbox
        • The platform's addresses
        • Add a platform address
        • One address, with its counts
        • Change an address's label, routing, or whether it accepts mail
        • Remove an address that holds no mail
        • Make, adopt or repair the address's routing rule
        • Every admin's personal address, made where missing
        • File a raw message, as if it had arrived
        • The inbox
        • One message, whole
        • Mark a message
        • Hand a message to an admin, or take it back
        • Leave an internal note
        • Reply, from the address the message came to
        • What is waiting
    • Databases
      • Databases
        • Data stores
          • Every data store on the account
          • Provision a data store
          • Change a data store that is already running
          • One data store
          • Deprovision it
          • Report what it is using
          • How to reach a data store
        • Connections and credentials
          • The api keys on a database
          • Issue a key
          • Revoke a key
          • The engine users we created
          • Create a user inside the database
          • Give a user a new password
          • Drop a user
          • How the database is reached
          • Set how it is reached
          • Revoke every api key on it
          • How to connect to it
          • The ssh keys that open its bastion
          • Add a key, or have one made
          • The private half of a generated key, once
          • Revoke an ssh key
        • Schema and objects
          • The SQL objects we put in it
          • Create one, and apply it
          • What is in the database, as the engine reports it
          • One table
          • What it would run, without running it
          • Redefine an object in place
          • Drop it
          • The extensions installed in it
        • Migrations
          • A plan compiled to statements, recording nothing
          • The migrations recorded for it
          • Record one
          • Apply everything recorded and not yet run
          • Apply everything pending, oldest version first
        • Lifecycle
          • Grow or shrink it
          • Stop it accepting connections
          • Start it again
          • Move it to another region
        • Backups and replicas
          • Take a backup
          • The backups it has
          • Restore one into it
          • What has been restored into it, and from where
          • Its read copies
          • Add one
        • Policies
          • The catalog
          • One policy
          • What this database is held to
          • Switch a policy on, or change its knobs
          • Switch it off
          • Mark the policies reviewed
          • Evaluate the periodic policies now
          • Who is behind a credential
        • Passwordless
          • The database's passwordless sessions
          • Issue a passwordless session (v1)
          • Revoke a passwordless session
          • Bind a session to a device key
          • Issue a v2 session for a host to bind
          • Redeem an enrolment ticket on the host
          • Check a passwordless credential
          • Run one described query under a passwordless credential
        • Database roles
          • The database's roles
          • Define a role
          • One role
          • Change what a role permits
          • Delete a role, and revoke every key granted it
          • Grant a role, which mints a key
          • Who holds a role
          • The api keys bound to a role
        • Pools
          • A database's connection pools, and how busy each is
          • Open another pool
          • Rename a pool or change its size
          • Close a pool
        • Data plane
          • Run a query against a database
          • Several statements, in order, over one connection
          • Is this database answering
          • What the proxy itself is holding
        • Transfers
          • The strategies this account's tier may use
          • Price a transfer without creating it
          • The account's transfer jobs, newest first
          • Create a transfer job
          • One job, and whether its certificate holds
          • Cancel an unfinished job
          • Start a created job, confirming its price
          • Report a job's status (the runner, or the owner's side of a local run)
        • Every database on the account
        • Provision a database
        • Change a database that is already running
        • One database
        • Deprovision it
        • Read or write it
        • Report what it is using
        • The engines this API will provision
        • Where a managed database can be put
    • Teams
      • Teams
        • Members
          • Who is on it
          • Invite somebody
          • Accept an invitation
          • Change somebody's role
          • Remove somebody
        • Projects
          • The projects a team runs
          • Start one
          • Rename a project, or move its environment
          • Delete a project
          • One project, and what is in it
          • Put a database or store in it
          • What is in a project
          • Take one out
        • The teams this account is on
        • Start one
        • The twelve roles, and what each may do
        • Rename a team
        • Close a team
        • One team
        • Hand the team to somebody else
        • Leave a team
    • Schemas
      • Error
      • ValidationErrors
      • Token
      • PolicyCategory
      • PolicySeverity
      • PolicyAction
      • PolicyTrigger
      • PolicyParam
      • Policy
      • PolicyCatalog
      • PolicyAssignment
      • PolicyOutcome
      • PolicyFiring
      • CredentialTrace
      • Relation
      • Restrictions
      • ChildSummary
      • SignupRequest
      • SigninRequest
      • UpdateMeRequest
      • User
      • Address
      • GeoPoint
      • D1Region
      • Usage
      • UsageReport
      • Resource
      • Database
      • DataStore
      • NewDatabase
      • NewDataStore
      • QueryRequest
      • DatabasePrivilege
      • ApiKey
      • DbUser
      • Access
      • AccessRequest
      • DatabaseObject
      • NewDatabaseObject
      • NewMigration
      • SchemaOperation
      • Migration
      • Operation
      • Session
      • AdminPowers
      • Admin
      • AuditEntry
      • TeamRole
      • Conversation
      • ChatMessage
      • TeamSso
      • Team
      • TeamMember
      • SshKey
      • ConnectionInfo
      • InboxAddress
      • InboxMailbox
      • InboxMessageSummary
      • InboxMessage
      • InboxNote
      • Page
      • Quote
      • Plan
      • ApiError
      • CapabilityRefusal
      • KlockErrorCode
      • PageWindow
      • SessionView
      • KlockStepUpRequest
      • KlockOpenRequest
      • KlockOpenedSession
      • UpdateMeResult
      • CapabilitiesView
      • SessionLimits
      • Device
      • DeviceListed
      • DeviceTeamRef
      • DeviceCommand
      • DeviceAuditLine
      • DeviceActionRequest
      • StaffActionRequest
      • ManagedSession
      • SessionRevoked
      • AccessRule
      • AccessRuleRequest
      • BehaviourProfile
      • BehaviourProfileRequest
      • BehaviourProfileSaved
      • BehaviourFinding
      • BehaviourFindingAck
      • StepUpProof
      • Removed
      • MemberLockdownRequest
      • McpClient
      • McpDelegatedView
      • McpToolCall
      • McpForwardRequest
      • PasswordlessScope
      • RoleScope
      • PasswordlessSession
      • PasswordlessTlsMaterial
      • PasswordlessKerberosMaterial
      • ServiceDeviceKeys
      • ServiceSession
      • DatabaseRole
      • TransferEndpoint
      • TransferJobRequest
      • TransferQuote
      • TransferStrategy
      • TransferJob
      • TransferJobAccess
      • Pool
      • PoolAllowance
      • BillingSubscription
      • Invoice
      • BillingContact
      • PaymentMethod
      • UpcomingCharges
      • TeamBilling
      • TeamKerberosRealm
      • TeamSsoDomain
      • TeamSsoResponse
      • StoreConnection
      • BatchFailure
      • ProxyStatus
  1. guides

klock-errors

klock error reference#

Every error the klock family can raise — 221 codes across the API, the klock
service, the CLI and device agent, the library and outh — with what it means, why it
happens and what to do. The catalog in src/klock/errors.ts is the single source of
truth; this page is generated from it, and a test fails when the code emits a code that
is not here.
On the wire an error is { "error": "<code>", "message": "…" }, with the HTTP
status below. Some carry more: needs and unlock (capability_missing,
step_up_required), reason (session_revoked), sessions (session_limit). A 401
to a klock session also carries WWW-Authenticate: Klock error="<code>".
Over RPC between the API and the klock service, the error is an Error whose
message starts with the code: device_not_found: no device dev_….
Locally, the device agent and library throw classes with their own short codes
(JwsError bad-signature, KlockFileError mode); each maps to an entry here,
listed as Local codes. explainKlockError(err) from ts-prorm-orm/klock does the
mapping for you, and also recognises the v1 messages that never had a code.
In the CLI, a klock failure prints its fix and a link to its entry here, under
What to do (<code>).
See klock for the file format and cryptography, and
CLI for the commands named below.

What now? A decision chart#

By HTTP status#

StatusCodes
400admin_not_delegable, bad_arguments, bad_intent, bad_nonce, bad_request, confirm_code_mismatch, confirm_code_required, csr_invalid, csr_key_type, csr_subject_mismatch, device_mismatch, grant_invalid, intent_mismatch, invalid_profile, invalid_rule, kind_unsupported, mfa_not_enrolled, not_delegable, password_browser_only, reason_required, recovery_failed, rotation_proof_invalid, seal_binding_invalid, team_not_active, totp_required, transfer_chunk_invalid, transfer_key_invalid, transfer_manifest_invalid, transfer_manifest_sig_invalid, unknown_capability, v1_query_invalid
401bad_digest, bad_pop, bad_signature, check_in_required, clock_skew, csr_attestation_invalid, device_key_mismatch, device_pending, device_revoked, device_suspended, fresh_signin_required, gate_auth_refused, gate_token_expired, gate_token_invalid, gate_token_missing, gate_token_not_yet_valid, gate_token_replayed, grant_expired, grant_invalid, klock_unusable, nonce_replayed, nonce_reused, recovery_failed, session_required, session_revoked, signature_expired, signature_incomplete, signature_invalid, signature_malformed, step_up_failed, step_up_required, ticket_expired, ticket_invalid, ticket_used, token_expired, token_invalid, token_revoked, unauthenticated, unknown_device, unsigned, v1_client_cert_required, v1_kerberos_refused
403access_denied, assumed_identity, capability_missing, capability_required, console_only, device_key_revoked, device_signature_required, gate_scope_refused, mfa_required, not_bound, not_this_session, not_yours, provider_unavailable, service_session_scope, step_up_required, transfer_recipient_refused, v1_beyond_session, v1_credential_malformed, v1_grant_not_canonical, v1_role_gone, v1_role_mismatch, v1_session_unusable, v1_signature_mismatch, v1_window_expired, v1_window_not_started, v1_wrong_database, wrong_subject
404credential_not_found, not_found, pairing_not_found, provider_unknown, team_not_found, tool_not_found, transfer_not_found, unknown_team, v1_unknown
405method_not_allowed
409already_bound, already_rotated, credential_not_active, device_key_enrolled, device_key_in_use, kerberos_realm_missing, pairing_kind_mismatch, pairing_used, resource_in_other_team, session_limit, session_revoked, subject_unavailable, sync_rollback, sync_seq_ahead, transfer_chunk_exists, transfer_incomplete, would_lock_you_out
410login_v2_required, pairing_expired, transfer_chunk_missing, transfer_expired, transfer_sender_revoked
413body_too_large, transfer_too_large
422csr_invalid, csr_key_type, csr_subject_mismatch
423lockdown, session_frozen
426upgrade_required
428confirmation_required
429rate_limited, too_many_attempts, transfer_quota_exceeded
500gate_query_failed, internal
501not_implemented
502authority_unavailable, certify_failed, klock_service_unavailable, transfer_chunk_corrupt
503access_check_unavailable, api_unavailable, authority_unavailable, capabilities_unavailable, klock_v2_unavailable, mcp_unavailable, no_keyset, policy_unavailable, secrets_key_missing, v1_kerberos_unavailable
none (local or RPC)canonical_json_invalid, cert_invalid, command_invalid, crypto_unavailable, device_key_invalid, device_key_missing, device_not_found, feed_invalid, grant_not_yet_valid, grant_wrong_audience, grant_wrong_device, grant_wrong_issuer, idle_timeout, invalid_state, jws_bad_alg, jws_bad_header, jws_bad_payload, jws_bad_signature, jws_bad_typ, jws_malformed, jws_unknown_kid, keychain_write_failed, keyset_invalid, keyset_rollback, keytab_invalid, klock_coordinates_missing, klock_format_invalid, klock_io_failed, klock_key_unpublished, klock_mode_insecure, klock_not_found, klock_overwrite_refused, klock_path_invalid, klock_read_only, klock_roots_invalid, klock_secret_length, klock_secret_missing, klock_secret_ref_unresolved, klock_tampered, klock_unconfigured, klock_version_unsupported, klock_wrong_kind, rpc_args_mismatch, rpc_bad_signature, rpc_clock_skew, rpc_malformed, rpc_replay, rpc_unsigned, rpc_wrong_audience, rpc_wrong_caller, rpc_wrong_method, seal_auth_failed, seal_invalid, session_expired, session_unknown, sync_bad_envelope, sync_bad_grant, sync_http, sync_network, sync_no_device, sync_nonce_mismatch, sync_response_rollback, tls_delivery_invalid, tls_key_invalid, tls_not_enrolled, tls_store_failed, tls_unavailable, unknown_kind

Codes by category#

CategoryCodes
Sessions and sign-in38
Capabilities and step-up22
Grants6
Devices and enrolment38
Sync11
Signatures and cryptography29
The .klock file14
The local gate8
Configuration and keys12
Protocol and RPC27
v1 passwordless grants16

Sessions and sign-in#

already_bound#

Already bound to another device key. · HTTP 409 · retryable: no · since 4.9.2
Message: That session is bound to another device key; rotate that key, or revoke the session and issue another
What it means. The passwordless session (or the transfer job) already has a service session on a different device key. A subject is held by one key at a time; moving it is a rotation, which the current holder signs.
Fix.
1.
On the current holder: prorm klock rotate.
2.
Or revoke it (prorm sessions revoke <id>) and bind the new key.
Raised by: API (api/security/controllers/klock.ts).
Related: already_rotated.

already_rotated#

The session was already rotated. · HTTP 409 · retryable: no · since 4.9.2
Message: This session has already been rotated
What it means. A key rotation for this session is done or in progress; each is idempotent by rotationId.
Fix.
1.
Run prorm klock sync to pick up the rotated key.
Raised by: API (api/security/controllers/klock.ts).

assumed_identity#

Not while assuming an identity. · HTTP 403 · retryable: no · since 4.9.2
Message: An assumed identity cannot open or change klock sessions.
What it means. Support staff acting as a user cannot open or change that user’s klock sessions.
Fix.
1.
Stop assuming the identity; the user signs in themselves.
Raised by: API (api/basic/routes/security.js).

check_in_required#

The session must check in. · HTTP 401 · retryable: yes · since 4.9.2
Message: sync needed (past the check-in deadline)
What it means. The session is past its checkInBy deadline: offline, only public and local:use capabilities are honoured until the device syncs. The CLI treats this code as a refresh signal, and a service gate (db serve v2, a host agent) raises it for gated operations past a service grant’s checkInBy; the API itself does not send it (online, it checks the session live and lets the grant expire).
Fix.
1.
Connect to the network and run prorm klock sync.
2.
If it still fails, prorm login.
Raised by: CLI (src/cli/core/cloud.ts), device agent / klock core (src/klock/agent/session.ts), device agent / klock core (src/klock/providers/db.ts).
Related: grant_expired.

confirm_code_mismatch#

The confirm code does not match. · HTTP 400 · retryable: no · since 4.9.2
Message: The confirm code does not match the one the terminal printed
What it means. The code in the console is not the one this terminal printed. The link may have come from someone else.
Fix.
1.
Do not approve it. Run prorm login yourself and compare the code on both screens.
Raised by: API (api/security/controllers/klock.ts).

confirm_code_required#

The confirm code is required. · HTTP 400 · retryable: no · since 4.9.2
Message: Opening a session from the console needs the state and confirm code 'prorm login' printed
What it means. The console must show and send back the code the terminal printed; this protects against a crafted sign-in link.
Fix.
1.
Start again with prorm login and open the link it prints.
Raised by: API (api/security/controllers/klock.ts).
Related: confirm_code_mismatch.

console_only#

Open klock sessions from the console. · HTTP 403 · retryable: no · since 4.9.2
Message: Open a klock session from the console ('prorm login'), not with a CLI token
What it means. A legacy CLI token tried to open a v2 klock session. Sessions are opened by the console sign-in flow, which shows a confirm code.
Fix.
1.
Run prorm login and approve it in the browser.
Raised by: API (api/security/controllers/klock.ts).

fresh_signin_required#

This needs a fresh sign-in. · HTTP 401 · retryable: yes · since 4.9.2
Message: Releasing a lockdown needs a fresh sign-in
What it means. Releasing a lockdown needs a session opened within the last 15 minutes (and the second factor now, when the account has one), or a recovery session: a session from before the lockdown was revoked by it, and an old one is not proof enough.
Fix.
1.
Sign in again (prorm login), then prorm lockdown release within 15 minutes.
Raised by: API (api/basic/routes/lockdown.js).
Related: lockdown, step_up_required.

idle_timeout#

The session idled out. · HTTP — · retryable: no · since 4.9.2
Message: idle_timeout
What it means. Nothing used the session for longer than its idle limit (7 days; 30 minutes for admin). The API revokes it with reason: idle; sessionIsLive returns this code over RPC; locally the agent reports sync needed.
Fix.
1.
Run prorm klock sync; if the server has already revoked it, prorm login.
Raised by: API (api/security/controllers/klock.ts), device agent / klock core (src/klock/agent/session.ts).
Related: session_revoked.

kind_unsupported#

A service session needs a resource it can stand for. · HTTP 400 · retryable: no · since 4.9.2
Message: A service session is opened over a database or a local transfer job: resource {kind: "database" | "transfer-job", id}
What it means. A kind: "service" session was asked for without a resource, or over a kind of resource no service session stands for (a store). Service sessions are bound to one passwordless database session or one local transfer job.
Fix.
1.
Bind an existing passwordless session to the holder’s key: prorm klock upgrade on the holder.
2.
Or open one with resource: {kind: "database", id, role, scope} or {kind: "transfer-job", id}.
Raised by: API (api/security/controllers/klock.ts).

klock_unusable#

Your klock session cannot be used. · HTTP 401 · retryable: no · since 4.9.2
Message: Your klock session cannot be used ({reason}). Run 'prorm login' again.
What it means. After a v2 sign-in the CLI never falls back to a legacy bearer token. The klock session on this machine is expired, revoked, tampered, missing its device key, or past its check-in deadline, so the request was not sent at all. The reason in brackets says which.
Fix.
1.
Run prorm klock sync if the reason says a sync is needed.
2.
Otherwise sign in again: prorm login.
3.
To use a legacy token deliberately, pass --token or set PRORM_TOKEN.
Raised by: CLI (src/cli/core/cloud.ts).
Related: grant_expired, klock_tampered, check_in_required.

lockdown#

The account is locked down. · HTTP 423 · retryable: yes · since 4.9.2
Message: This account is locked down. Use account recovery, or wait for it to end.
What it means. Somebody ran prorm lockdown (or the console’s Danger zone) on this account: every session was revoked, devices were suspended, and for 15 minutes every request of the account is refused — including from a session signed in after the lockdown. The body’s lockdownUntil says when the window ends.
Common causes.
You locked the account down yourself after a scare, and signed in again before the window ended.
Somebody with your password and second factor locked it down.
Fix.
1.
Wait until lockdownUntil, sign in again, and run prorm lockdown release (it needs your authenticator code).
2.
Or recover now by email: the console’s Account recovery (#/recover) gives a one-hour session that gets through the lockdown and can release it.
3.
Reinstate your devices one by one afterwards: prorm devices reinstate <id>.
Raised by: API (api/middleware/accessRules.js), API (api/basic/routes/lockdown.js), klock service (api/klock/contract.ts).
Related: access_denied, fresh_signin_required.

login_v2_required#

Legacy CLI tokens are no longer issued. · HTTP 410 · retryable: no · since 4.9.2
Message: This API no longer issues legacy CLI tokens at sign-in. Update the CLI and run 'prorm login' (klock v2).
What it means. From enforcement E3 (CAPABILITY_E3=1) the login flow (POST /security/sessions/cli and the v1 relay POST /security/cli-logins) stops minting v1 bearer tokens. Tokens already issued keep working until they expire. An explicit personal token (purpose: "token", 30 days at most) is still issued for --token / PRORM_TOKEN.
Fix.
1.
Update the CLI and sign in again with prorm login, which opens a klock v2 session.
2.
For scripts, create an explicit token (the console CLI tokens page) and pass it with --token or PRORM_TOKEN.
Raised by: API (api/basic/routes/security.js).

mfa_not_enrolled#

No second factor to step up with. · HTTP 400 · retryable: no · since 4.9.2
Message: This account has no second factor to step up with
What it means. A TOTP step-up needs a confirmed second factor.
Fix.
1.
Enrol one: prorm security mfa enable, then prorm step-up.
Raised by: API (api/security/controllers/klock.ts).

mfa_required#

Admins need a second factor. · HTTP 403 · retryable: no · since 4.9.2
Message: Admin accounts need a TOTP second factor. Enrol one, then try again.
What it means. From enforcement E3 (CAPABILITY_E3=1) every admin account must have a confirmed TOTP second factor, and the admin routes refuse an admin without one. The body carries enrol.setup and enrol.confirm, the enrolment routes, which stay open to the admin.
Fix.
1.
Enrol a second factor: prorm security mfa enable (or the console security page), which calls POST /security/mfa/setup then POST /security/mfa/confirm.
2.
Then retry; a klock session steps up with prorm step-up --totp <code> before admin writes.
Raised by: API (api/auth.js).
Related: mfa_not_enrolled, step_up_required.

not_bound#

Not bound to a device key. · HTTP 403 · retryable: no · since 4.9.2
Message: This session is not bound to a device key: use its v1 credential, or bind it (prorm klock upgrade)
What it means. A device-signed (klock v2) request reached a passwordless session, or a transfer job, that has no service session on a device key. v1 sessions and jobs keep their v1 credential (the HMAC grant, the report MAC) until they are bound.
Fix.
1.
Keep using the v1 credential, or bind it: prorm klock upgrade on the holder.
2.
For a transfer job: create it with --klock-v2, which enrols the agent.
Raised by: API (api/security/routes/passwordless.js), API (api/basic/controllers/transfers.ts).
Related: device_signature_required.

not_this_session#

Only the session itself may do this. · HTTP 403 · retryable: no · since 4.9.2
Message: Only the session itself may do this
What it means. Some session actions (rotating its key, refreshing its grant) may only be made by the session they concern.
Fix.
1.
Run the command on the device that holds that session.
Raised by: API (api/security/controllers/klock.ts).

not_yours#

That grant is not yours to hand over. · HTTP 403 · retryable: no · since 4.9.2
Message: That grant is not yours to hand over
What it means. The console tried to park a grant for the CLI sign-in relay that belongs to another account.
Fix.
1.
Sign in to the console as the account the terminal is signing in to, then prorm login again.
Raised by: API (api/basic/routes/security.js).

password_browser_only#

Password step-up is for the browser. · HTTP 400 · retryable: no · since 4.9.2
Message: A password step-up is for the browser; use a TOTP code
What it means. A klock-signed request cannot step up with a password.
Fix.
1.
Use prorm step-up --totp <code>, or prorm step-up --browser.
Raised by: API (api/security/controllers/klock.ts).

recovery_failed#

Account recovery failed. · HTTP 400 / 401 · retryable: no · since 4.9.2
Message: That recovery link or its details are not valid
What it means. The recovery code is unknown, expired (30 minutes), or already used, or the password or second factor with it was wrong. Which one is deliberately not said. Repeated failures lock recovery for a while, like sign-in.
Fix.
1.
Ask for a new link from the console’s Account recovery page, and use it within 30 minutes.
2.
Send your account password and, if the account has a second factor, your authenticator code or a recovery code.
Raised by: API (api/basic/routes/recovery.js).
Related: access_denied, too_many_attempts.

rotation_proof_invalid#

The key rotation proof was refused. · HTTP 400 · retryable: no · since 4.9.2
Message: The new key's proof was refused: {reason}
What it means. A rotation must be cross-signed by the old and the new key; the proof did not verify.
Fix.
1.
Retry with prorm klock rotate; if it persists, prorm login to enrol afresh.
Raised by: API (api/security/controllers/klock.ts).

service_session_scope#

A service session is used only for what it stands for. · HTTP 403 · retryable: no · since 4.9.2
Message: A service session is used only for what it stands for (its database session or transfer job), and to check in or rotate
What it means. A service session’s grant (a db host, a CI runner, a transfer agent) was used on an account route. It holds one capability over one resource and authenticates only that resource’s data plane, its own check-in (refresh) and its key rotation — never the owner’s account, and never admin.
Fix.
1.
Use the owner’s own session for account routes: prorm login on a machine the owner uses.
2.
On the service host, use the klock only for its database (passwordless exchange/query) or its transfer job’s reports.
Raised by: API (api/security/controllers/klock.ts).
Related: wrong_subject.

session_expired#

The session has expired. · HTTP — · retryable: no · since 4.9.2
Message: session_expired
What it means. The session is past its expiresAt / maxDuration. On the wire the API answers session_revoked with reason: expired; this code is what sessionIsLive returns to the klock service over RPC, and what the CLI also accepts.
Fix.
1.
Sign in again: prorm login.
Raised by: API (api/security/controllers/klock.ts), device agent / klock core (src/klock/agent/session.ts).
Related: session_revoked.

session_frozen#

The session is frozen. · HTTP 423 · retryable: no · since 4.9.2
Message: This klock session is frozen
What it means. The session was frozen (by you, a team admin, or a behaviour profile). Every request is refused until it is unfrozen with a step-up.
Fix.
1.
From another signed-in session: prorm step-up, then prorm sessions unfreeze <id>.
2.
Or revoke it and sign in again: prorm login.
Raised by: API (api/security/controllers/klock.ts).
Related: step_up_required.

session_limit#

Too many sessions of this kind. · HTTP 409 · retryable: no · since 4.9.2
Message: You have {count} {kind} sessions, the most allowed. Revoke one first.
What it means. The account is at its concurrent-session limit for this kind and the limit’s eviction is refuse. The body lists the live sessions.
Fix.
1.
List them: prorm sessions.
2.
Revoke one you no longer use: prorm sessions revoke <id>.
3.
Then run the command again.
Raised by: API (api/security/controllers/klock.ts).

session_required#

The device has no klock session. · HTTP 401 · retryable: no · since 4.9.2
Message: The device holds no klock session
What it means. Credentials are issued to a device’s live, device-bound session. This device is enrolled but its session is missing (never opened, or its row is gone).
Fix.
1.
Sign in on this device: prorm login.
Raised by: klock service (api/klock/lib/credentials.ts), API (api/security/controllers/klockCredentials.ts).
Related: session_revoked.

session_revoked#

The session has ended. · HTTP 401 / 409 · retryable: no · since 4.9.2
Message: This klock session has ended ({reason}). Sign in again.
What it means. The session behind the grant was revoked, expired (reason: expired), idled out (reason: idle), does not exist (unknown), is not device-bound, or its account is gone. The CLI drops the local session when it sees this. As 409 it means the session you tried to revoke is already revoked.
Fix.
1.
Sign in again: prorm login.
2.
If you did not revoke it, review prorm sessions and prorm security audit.
Raised by: API (api/security/controllers/klock.ts), klock service (api/klock/contract.ts), MCP Worker (workers/mcp/src/auth.ts).
Related: session_expired, idle_timeout, device_revoked.

session_unknown#

No such session. · HTTP — · retryable: no · since 4.9.2
Message: session_unknown
What it means. sessionIsLive (API ← klock service RPC) found no session for the id. Over HTTP the API answers session_revoked with reason: unknown.
Fix.
1.
Sign in again: prorm login.
Raised by: API (api/security/controllers/klock.ts).
Related: session_revoked.

step_up_failed#

The step-up was refused. · HTTP 401 · retryable: yes · since 4.9.2
Message: That code is not right
What it means. The TOTP code or password given for a step-up is wrong. Failures count towards a lock-out.
Fix.
1.
Check the time on your authenticator device and run prorm step-up again with a fresh code.
Raised by: API (api/security/controllers/klock.ts).
Related: too_many_attempts, step_up_required.

subject_unavailable#

Nothing left to bind. · HTTP 409 · retryable: no · since 4.9.2
Message: That passwordless session is revoked or expired
What it means. A service session was asked for over a passwordless session that is revoked or past its expiry, a finished transfer job, or a binding that has already ended.
Fix.
1.
Issue a new passwordless session (prorm passwordless issue) or create a new job, then bind that.
Raised by: API (api/security/controllers/klock.ts).

team_not_active#

Not an active member of that team. · HTTP 400 · retryable: no · since 4.9.2
Message: That team is not one you are an active member of
What it means. A session was asked to act for a team you are not an active member of (invited, suspended or removed).
Fix.
1.
Check prorm teams list; accept the invitation or pick another team.
Raised by: API (api/security/controllers/klock.ts), library (src/capabilities.ts).
Local codes: CapabilityResolutionError:team_not_active.
Related: team_not_found.

team_not_found#

No such team. · HTTP 404 · retryable: no · since 4.9.2
Message: You are not an active member of that team
What it means. The team named for the session is not one you belong to.
Fix.
1.
Check the team id with prorm teams list.
Raised by: API (api/security/controllers/klock.ts).
Related: unknown_team.

token_expired#

The MCP client token has expired. · HTTP 401 · retryable: no · since 4.9.2
Message: That MCP client token has expired
What it means. The delegated token passed its expiry (at most 30 days), or went unused for longer than its idle timeout and was revoked.
Fix.
1.
Create a new token: prorm mcp clients create --name "<client>" --caps … --days <n>.
Raised by: API (api/security/controllers/mcpForward.ts).
Related: token_invalid.

token_invalid#

The MCP client token is not valid. · HTTP 401 · retryable: no · since 4.9.2
Message: That MCP client token is not valid
What it means. The /security/mcp/* routes take only a delegated MCP client token (Authorization: Bearer prorm_dt_…), and this one is unknown, malformed, not a delegated token, or its account no longer exists.
Fix.
1.
Create a new token: prorm mcp clients create --name "<client>" --caps …, and put it in the client’s config.
2.
Check that the whole token was copied, including the prorm_dt_ prefix.
Raised by: API (api/security/controllers/mcpForward.ts).
Related: token_revoked, token_expired.

token_revoked#

The MCP client token was revoked. · HTTP 401 · retryable: no · since 4.9.2
Message: That MCP client token was revoked
What it means. The delegated token was revoked: by prorm mcp clients revoke, from the console, by a lockdown, or when the local prorm mcp that created it stopped.
Fix.
1.
Create a new token with prorm mcp clients create, or restart prorm mcp.
Raised by: API (api/security/controllers/mcpForward.ts).
Related: token_invalid.

too_many_attempts#

Too many step-up attempts. · HTTP 429 · retryable: yes · since 4.9.2
Message: Too many step-up attempts. Try again in a few minutes.
What it means. Repeated failed step-ups lock the step-up out for a few minutes.
Fix.
1.
Wait a few minutes, then prorm step-up with a fresh code.
Raised by: API (api/security/controllers/klock.ts).

totp_required#

Step up with a TOTP code. · HTTP 400 · retryable: no · since 4.9.2
Message: This account has a second factor: step up with a TOTP code
What it means. A password step-up is only for accounts without a second factor.
Fix.
1.
Run prorm step-up --totp <code>.
Raised by: API (api/security/controllers/klock.ts).

wrong_subject#

That service session stands for something else. · HTTP 403 · retryable: no · since 4.9.2
Message: That service session stands for something else
What it means. A device-signed request reached a passwordless session or a transfer job its service session is not bound to — another database session, another job, a job whose agent was replaced — or an account session was presented where only the bound service session is accepted.
Fix.
1.
Use the klock bound to this session or job (prorm klock show).
2.
Bind this one to the host’s key: prorm klock upgrade, or open an agent session for the job.
Raised by: API (api/security/controllers/klock.ts), API (api/basic/controllers/transfers.ts).
Related: service_session_scope, not_bound.

Capabilities and step-up#

access_check_unavailable#

Access rules could not be checked. · HTTP 503 · retryable: yes · since 4.9.2
Message: Access rules could not be checked right now. Try again shortly.
What it means. The account, team, device or resource has access rules, and an internal error (a database hiccup, say) stopped the API judging them. It refuses rather than let the request through unchecked (PRORM-SA-2026-064).
Fix.
1.
Retry after the Retry-After seconds.
2.
Report it if it persists.
Raised by: API (api/middleware/accessRules.js).
Related: access_denied.

access_denied#

An access rule denied the request. · HTTP 403 · retryable: no · since 4.9.2
Message: access_denied
What it means. An enforcing access rule — on your account, a team you are acting in, the device, or the database or store — denies this request (block beats allow; a team’s mandatory allowlist must also hold). The response never says which rule matched; the account’s audit log does (access.denied).
Common causes.
You are somewhere an allowlist leaves out (another address, country or network).
A new rule finished its 24-hour report period and now enforces.
A team’s mandatory allowlist applies to requests in the team’s context.
Fix.
1.
From somewhere allowed, check the rules: prorm access list and prorm access test.
2.
Locked out of your own account? Use email recovery (the console’s #/recover): it skips account rules for an hour.
3.
For a team’s rule, ask a team owner or admin.
Raised by: API (api/middleware/accessRules.js).
Related: would_lock_you_out, lockdown, recovery_failed.

admin_not_delegable#

Admin capabilities are never delegated. · HTTP 400 · retryable: no · since 4.9.2
Message: Admin capabilities are never delegated
What it means. An admin:* capability was asked for on an MCP client token. Admin work needs a Klock session with a fresh step-up; no bearer ever holds it.
Fix.
1.
Remove every admin:* capability from --caps.
Raised by: API (api/security/controllers/mcpForward.ts).
Related: not_delegable.

capabilities_unavailable#

Capabilities could not be resolved. · HTTP 503 · retryable: yes · since 4.9.2
Message: Could not resolve capabilities right now
What it means. GET /me/capabilities could not resolve the principal’s capabilities (a database hiccup).
Fix.
1.
Retry in a moment. The CLI falls back to its cached view meanwhile.
Raised by: API (api/basic/routes/me.js), MCP Worker (workers/mcp/src/auth.ts).

capability_missing#

This session cannot do that. · HTTP 403 · retryable: no · since 4.9.2
Message: This session cannot do that
What it means. The route needs a capability (needs) this session’s ceiling, your team role, or the API key does not have. The body’s unlock says what would give it: login, upgrade, team-role, step-up or none.
Fix.
1.
unlock: login — sign in: prorm login.
2.
unlock: upgrade — the plan does not include it: prorm billing plans.
3.
unlock: team-role — ask a team owner or admin for a role that allows it.
4.
unlock: none — an API key or narrowed session cannot do it; use a full session.
Raised by: API (api/middleware/capabilities.js), API (api/basic/routes/provision.js), API (api/basic/routes/transfers.js).
Related: step_up_required, unauthenticated.

capability_required#

The session lacks the capability for this credential. · HTTP 403 · retryable: no · since 4.9.2
Message: A {provider} credential needs {caps}
What it means. The device’s session does not hold the capability the provider needs: klock:sync for a person’s device, passwordless:use for a database host’s service session. It is re-resolved from live facts at issue. The same code covers a device kind that cannot hold the provider.
Fix.
1.
Sign in on this device with an interactive session (prorm login).
2.
For a db host, bind it to a passwordless session first (prorm klock upgrade).
Raised by: klock service (api/klock/lib/credentials.ts), API (api/security/controllers/klockCredentials.ts).
Related: provider_unavailable.

confirmation_required#

A destructive MCP tool needs confirming. · HTTP 428 · retryable: yes · since 4.9.2
Message: confirmation required: call again with confirm "{confirm}"
What it means. The tool is destructive (it deletes or revokes something). The first call answers with a confirmation token bound to the caller, the tool and these exact arguments, good for about two minutes, so the person sees the action before it happens.
Fix.
1.
Show the action to the person. Once they agree, call the tool again with the same arguments plus confirm: "<token>".
2.
A token for other arguments, or one older than about four minutes, is refused with a new token.
Raised by: API (api/security/controllers/mcpForward.ts).

invalid_profile#

That behaviour profile is not valid. · HTTP 400 · retryable: no · since 4.9.2
Message: Invalid behaviour profile
What it means. The profile failed the profile schema (https://prod-orm.io/schemas/klock-profile.v1.json) or its extends does not resolve, the preset is unknown, the mode is not report or enforce, or the scope is not account, team, device, session or service.
Fix.
1.
Check it locally first: prorm behaviour test --file profile.json.
2.
prorm behaviour presets lists the presets a profile can extend (extends: "preset:<name>").
Raised by: API (api/controllers/behaviour.ts).

invalid_rule#

That access rule is not valid. · HTTP 400 · retryable: no · since 4.9.2
Message: That rule is not valid
What it means. The rule failed the shared engine’s validation (an address that is not a CIDR, a country that is not ISO 3166, a time window that does not parse, an unknown dimension or effect), names a reserved note, would be one rule too many for its scope (200), or is a lockdown being removed through the rule routes. The body’s problems lists each problem.
Fix.
1.
Fix what problems lists; prorm access add --help shows each dimension’s value.
2.
End a lockdown with prorm lockdown release, not by removing its rule.
Raised by: API (api/controllers/accessRules.ts).
Related: would_lock_you_out.

not_delegable#

That capability cannot be delegated. · HTTP 400 · retryable: no · since 4.9.2
Message: These capabilities cannot be given to an MCP client
What it means. A delegated MCP client token holds at most the delegated session mask: never other members’ devices or sessions, team-wide rules or profiles, or the right to create further MCP clients.
Fix.
1.
Drop the capabilities listed in notDelegable from --caps.
2.
Do that work from your own signed-in session instead.
Raised by: API (api/security/controllers/mcpForward.ts).
Related: admin_not_delegable, unknown_capability.

provider_unavailable#

The provider is not on your plan. · HTTP 403 · retryable: no · since 4.9.2
Message: The {provider} provider is not available on the {plan} plan
What it means. Credential providers are plan entitlements. TLS client certificates need a paid plan (starter, usage, membership or pro). In a team context the team’s plan applies.
Fix.
1.
Upgrade the plan (prorm billing), or use the team whose plan includes it.
2.
Without it, use the session’s device signature, which every plan has.
Raised by: klock service (api/klock/lib/credentials.ts), API (api/security/controllers/klockCredentials.ts).
Related: capability_required.

resource_in_other_team#

The resource belongs to another team. · HTTP 409 · retryable: no · since 4.9.2
Message: That {kind} is already shared with another team. A resource belongs to at most one team: detach it there first.
What it means. A resource belongs to at most one team. The API sends this code in the body’s code field (with the message in error).
Fix.
1.
Detach it from the other team’s project first, then attach it here.
Raised by: API (api/controllers/ownership.ts).

step_up_required#

This needs a fresh step-up. · HTTP 401 / 403 · retryable: yes · since 4.9.2
Message: This needs a fresh step-up: prorm step-up
What it means. The capability is dormant until a fresh step-up (TOTP): admin capabilities, unsafe admin methods, unfreezing, and opening device sessions. Klock sessions get 401 with WWW-Authenticate: Klock error="step_up_required"; bearer sessions get 403.
Fix.
1.
Run prorm step-up (or prorm step-up --totp <code>), then the command again. On a terminal the CLI offers this itself.
Raised by: API (api/middleware/capabilities.js), API (api/auth.js), API (api/security/controllers/klock.ts).
Related: step_up_failed, capability_missing, mfa_not_enrolled.

tool_not_found#

No such MCP tool (or not for this session). · HTTP 404 · retryable: no · since 4.9.2
Message: Unknown tool
What it means. The MCP tool does not exist, or this session may not use it. The two get the same answer on purpose, so the tool list cannot be probed.
Common causes.
A typo in the tool name, or a tool from a newer registry than this API has.
A delegated MCP client token whose capabilities do not cover the tool.
An admin tool called with a bearer or a delegated token (admin tools need a Klock session and step-up).
Fix.
1.
List the tools this session can see (tools/list) and call one of those.
2.
For an MCP client token, create one with the capabilities the tool needs: prorm mcp clients create --caps ….
Raised by: API (api/security/controllers/mcpForward.ts).
Related: capability_missing.

transfer_quota_exceeded#

File transfer quota reached. · HTTP 429 · retryable: yes · since 4.9.2
Message: the file-transfer quota is reached
What it means. The transfer would take today’s total over the plan’s daily allowance (usage: 10 GB; membership and pro: 100 GB, over the last 24 hours), or the recipient already has 50 transfers waiting, or this device has 20 in flight.
Fix.
1.
Wait: the daily window rolls (the answer carries Retry-After).
2.
Ask the recipient to accept or refuse what is waiting (prorm klock inbox).
3.
Or move to a plan with a larger allowance: prorm billing plans.
Raised by: klock service (api/klock/routes/transfers.ts).
Related: transfer_too_large, rate_limited.

transfer_recipient_refused#

You cannot send files to that device. · HTTP 403 · retryable: no · since 4.9.2
Message: no device you may send files to has that name or id
What it means. The destination is not a device this session may send to: it does not exist, is another person’s device and no team you share gives you files:team, or it is suspended, revoked or has no certificate. All of these get the same answer, so the route does not reveal which device ids exist.
Common causes.
Sending to a teammate without files:team (roles owner, admin, operator) in a team you both belong to.
The recipient device is suspended or revoked.
A mistyped device id or name.
Fix.
1.
prorm devices list shows your own devices and their ids.
2.
For a teammate’s device, ask a team owner or admin for a role with files:team.
3.
To reach support, send to support: with --reason.
Raised by: klock service (api/klock/lib/transfer-policy.ts).
Related: capability_missing.

transfer_too_large#

The transfer is over the plan’s size limit. · HTTP 413 · retryable: no · since 4.9.2
Message: the transfer is over the per-transfer limit
What it means. The files add up to more than one transfer may carry on the plan that pays for it (usage: 2 GB; membership and pro: 10 GB; the relay never takes more than 10 GB). Nothing was stored.
Fix.
1.
Split the files over several prorm klock cp runs.
2.
Or move to a plan with a larger allowance: prorm billing plans.
Raised by: klock service (api/klock/routes/transfers.ts).
Related: transfer_quota_exceeded.

unauthenticated#

Sign in to do that. · HTTP 401 · retryable: no · since 4.9.2
Message: Sign in to do that
What it means. The route needs a signed-in principal and the request had none.
Fix.
1.
Sign in: prorm login.
Raised by: API (api/middleware/capabilities.js), MCP Worker (workers/mcp/src/auth.ts).

unknown_capability#

Unknown capability id. · HTTP 400 · retryable: no · since 4.9.2
Message: Unknown capability ids
What it means. A capability named for an MCP client token is not one this API knows: a typo, or a capability from a newer library.
Fix.
1.
Check the ids in unknown against prorm whoami or the capabilities guide.
2.
Use ns:* (for example resource:*) for a whole namespace.
Raised by: API (api/security/controllers/mcpForward.ts).
Related: not_delegable.

unknown_kind#

Unknown session kind. · HTTP — · retryable: no · since 4.9.2
Message: unknown session kind {kind}
What it means. Capability resolution was given a session kind it does not know — a newer server talking to an older library.
Fix.
1.
Upgrade the library/CLI.
Raised by: library (src/capabilities.ts).
Local codes: CapabilityResolutionError:unknown_kind.

unknown_team#

Unknown team. · HTTP 404 · retryable: no · since 4.9.2
Message: Unknown team
What it means. The team does not exist or you are not an active member. The API answers the same for both, on purpose.
Fix.
1.
Check the id with prorm teams list, or pass no team to act for yourself.
Raised by: API (api/basic/routes/provision.js), API (api/basic/routes/transfers.js), API (api/team/routes/teams.js).
Related: team_not_found.

would_lock_you_out#

That rule would lock you out. · HTTP 409 · retryable: no · since 4.9.2
Message: would_lock_you_out
What it means. Saving (or removing) the rule would deny your own current request once every rule is enforced — a new rule reports for 24 hours and then enforces, so it is judged as enforced. The body’s reasons say which allowlist or block it is; the CLI runs the same guard locally first.
Fix.
1.
Change the rule so it still admits where you are (prorm access test shows how a request is judged).
2.
If you mean it, save it with force: true (prorm access … --force): that needs a fresh step-up and a verified email address, which is how recovery reaches you.
Raised by: API (api/controllers/accessRules.ts), API (api/middleware/accessRules.js), device agent / klock core (src/klock/policy/access-rules.ts).
Related: access_denied, step_up_required.

Grants#

grant_expired#

The grant has expired. · HTTP 401 · retryable: yes · since 4.9.2
Message: The grant has expired; refresh it
What it means. The session’s grant (the API-signed token in the klock) is past its exp. Grants are short; the session behind them usually is not. The CLI syncs for a new grant and retries once automatically.
Fix.
1.
Run prorm klock sync (online).
2.
If the session itself has ended, prorm login.
Raised by: API (api/security/controllers/klock.ts), device agent / klock core (src/klock/jws.ts), device agent / klock core (src/klock/agent/session.ts), outh (Go) (outh/internal/klockv2/grant.go), MCP Worker (workers/mcp/src/auth.ts).
Local codes: JwsError:expired.
Related: session_revoked, check_in_required.

grant_invalid#

The grant was refused. · HTTP 401 / 400 · retryable: no · since 4.9.2
Message: The grant was refused: {reason}
What it means. The grant did not verify (signature, kid, issuer, audience), does not carry its device key, is a guest grant on an account route, or — on the sign-in relay — is not a grant this API signed. The klock service also reports a grant the API minted that it could not verify as grant_invalid.
Fix.
1.
Run prorm klock sync.
2.
If that fails, sign in again: prorm login.
Raised by: API (api/security/controllers/klock.ts), API (api/basic/routes/security.js), klock service (api/klock/lib/trust.ts), device agent / klock core (src/klock/agent/session.ts), MCP Worker (workers/mcp/src/auth.ts).
Related: grant_expired, klock_tampered, jws_bad_signature.

grant_not_yet_valid#

The grant is not valid yet. · HTTP — · retryable: yes · since 4.9.2
Message: the grant is not valid yet
What it means. The grant’s nbf is ahead of this machine’s clock, beyond the allowed skew.
Fix.
1.
Sync the system clock, then retry.
Raised by: device agent / klock core (src/klock/jws.ts), outh (Go) (outh/internal/klockv2/grant.go).
Local codes: JwsError:not-yet-valid.
Related: clock_skew.

grant_wrong_audience#

The grant is not for this service. · HTTP — · retryable: no · since 4.9.2
Message: the grant is not for {audience}
What it means. The grant’s aud does not include the verifier (api, klock, a database gate).
Fix.
1.
Sign in again for a grant with the right audience: prorm login.
Raised by: device agent / klock core (src/klock/jws.ts), outh (Go) (outh/internal/klockv2/grant.go).
Local codes: JwsError:wrong-audience.

grant_wrong_device#

The grant is bound to another device key. · HTTP — · retryable: no · since 4.9.2
Message: the grant is bound to another device key
What it means. The grant’s deviceKeyThumbprint is not this device’s key: the klock was copied from another machine, or the key was rotated without a new grant.
Fix.
1.
Run prorm klock sync; if that fails, prorm login to enrol this device.
Raised by: device agent / klock core (src/klock/jws.ts), outh (Go) (outh/internal/klockv2/grant.go).
Local codes: JwsError:wrong-device.
Related: device_key_mismatch.

grant_wrong_issuer#

The grant is from another API. · HTTP — · retryable: no · since 4.9.2
Message: the grant is from {iss}, not {issuer}
What it means. The grant’s iss is not the API this klock is for — for example a staging grant against production.
Fix.
1.
Check PRORM_API_URL / the profile, then prorm login against the right API.
Raised by: device agent / klock core (src/klock/jws.ts), outh (Go) (outh/internal/klockv2/grant.go).
Local codes: JwsError:wrong-issuer.

Devices and enrolment#

bad_pop#

The proof of possession does not verify. · HTTP 401 · retryable: no · since 4.9.2
Message: the proof of possession does not verify
What it means. Enrolment needs a signature by the new key over the ticket’s nonce; it was missing or wrong.
Fix.
1.
Retry prorm login; if it persists, upgrade the CLI.
Raised by: klock service (api/klock/lib/enrolment.ts), API (api/security/controllers/klock.ts).

cert_invalid#

The device certificate is not valid. · HTTP — · retryable: yes · since 4.9.2
Message: the device certificate does not verify: {reason}
What it means. Internal to the klock service: the API-signed device certificate did not verify. It reaches clients as certify_failed.
Fix.
1.
Retry; report it if it persists (a keyset mismatch between the API and the klock service).
Raised by: klock service (api/klock/lib/trust.ts).

certify_failed#

The API did not certify the device. · HTTP 502 · retryable: yes · since 4.9.2
Message: the API did not certify the device: {reason}
What it means. The klock service registered the device but the API’s certificate did not verify or did not arrive.
Fix.
1.
Retry prorm login in a moment.
Raised by: klock service (api/klock/lib/enrolment.ts).
Related: cert_invalid.

credential_not_active#

The credential is no longer current. · HTTP 409 · retryable: no · since 4.9.2
Message: the credential is {status}; request a new one
What it means. Renewing needs a current (or merely expired) credential, and revoking needs one that is not already revoked. This one was revoked or superseded.
Fix.
1.
Request a new one: prorm klock certs request.
Raised by: klock service (api/klock/lib/credentials.ts).

credential_not_found#

No such credential on this device. · HTTP 404 · retryable: no · since 4.9.2
Message: no such credential on this device
What it means. The credential id is not in the ledger, or it belongs to another device. The two cases are answered the same.
Fix.
1.
List this device’s credentials: prorm klock certs list.
Raised by: klock service (api/klock/lib/credentials.ts).

device_key_enrolled#

This device key is already enrolled. · HTTP 409 · retryable: no · since 4.9.2
Message: this device key is already enrolled
What it means. The key already has a device; enrolment is once per key.
Fix.
1.
Run prorm klock sync to use the existing enrolment.
Raised by: klock service (api/klock/lib/enrolment.ts).

device_key_in_use#

This device key is enrolled to someone else. · HTTP 409 · retryable: no · since 4.9.2
Message: this device key is enrolled to someone else
What it means. The key is enrolled to another account (a shared machine user, or a copied key).
Fix.
1.
Sign in as that account, or generate a new key: prorm logout, then prorm login.
Raised by: klock service (api/klock/lib/enrolment.ts).

device_key_invalid#

The device key is not a valid key. · HTTP — · retryable: no · since 4.9.2
Message: the {what} is not a 32-byte base64url key
What it means. The stored device key is not 32 bytes of base64url, or the device id is malformed.
Fix.
1.
Sign in again to make a new key: prorm login.
Raised by: device agent / klock core (src/klock/agent/devicekey.ts).
Local codes: DeviceKeyError:bad-key.

device_key_mismatch#

The device key does not match its enrolment. · HTTP 401 · retryable: no · since 4.9.2
Message: The grant is for another device key; enrol this device again
What it means. The request was signed by a key other than the one the grant or the enrolment names: a copied klock, a regenerated key, or a rotation the server has not seen.
Fix.
1.
Run prorm login to enrol this device again.
Raised by: API (api/security/controllers/klock.ts), klock service (api/klock/lib/device-auth.ts).
Local codes: HttpSigError:wrong-key.
Related: grant_wrong_device, klock_tampered.

device_key_missing#

The device key is missing. · HTTP — · retryable: no · since 4.9.2
Message: the {what} is missing
What it means. The klock names a device, but its private key is not in the keychain (or the file, for keyStore: file).
Common causes.
The keychain was reset, or the klock was copied to another machine.
Fix.
1.
Sign in again to enrol this machine: prorm login.
Raised by: device agent / klock core (src/klock/agent/devicekey.ts), device agent / klock core (src/klock/agent/index.ts).
Local codes: DeviceKeyError:missing.

device_key_revoked#

This device key was revoked. · HTTP 403 · retryable: no · since 4.9.2
Message: this device key was revoked; generate a new one
What it means. A revoked device key cannot enrol again.
Fix.
1.
Remove the old key and sign in, which makes a new one: prorm logout, then prorm login.
Raised by: klock service (api/klock/lib/enrolment.ts).

device_mismatch#

The request is for another device. · HTTP 400 · retryable: no · since 4.9.2
Message: deviceId is not the signing device
What it means. A sync named a deviceId that is not the device whose key signed it (over RPC: the session is bound to another device).
Fix.
1.
Use this device’s own klock; prorm login if it was copied from elsewhere.
Raised by: klock service (api/klock/routes/sync.ts), API (api/security/controllers/klock.ts).
Related: device_key_mismatch.

device_not_found#

No such device. · HTTP — · retryable: no · since 4.9.2
Message: device_not_found: no device {id}
What it means. The API asked the klock service (RPC) about a device it does not have.
Fix.
1.
Refresh the list: prorm devices list.
Raised by: klock service (api/klock/internal.ts).

device_pending#

The device is not approved yet. · HTTP 401 · retryable: yes · since 4.9.2
Message: the device is pending
What it means. The device is enrolled but waiting for approval (pairing, or a team requiring device approval).
Fix.
1.
Approve it from a trusted device: prorm devices pair <code>, or in the console.
Raised by: klock service (api/klock/lib/device-auth.ts).

device_revoked#

This device was revoked. · HTTP 401 · retryable: no · since 4.9.2
Message: the device is revoked
What it means. The device was revoked or wiped (from the console, another device, a team admin, or support). Its sessions are revoked too; the CLI drops the local session.
Fix.
1.
If that was intended, sign in again to enrol afresh: prorm login.
2.
If it was not, check prorm devices list and prorm security audit from another device.
Raised by: klock service (api/klock/lib/device-auth.ts), MCP Worker (workers/mcp/src/auth.ts).
Related: session_revoked, device_key_revoked.

device_suspended#

The device is suspended. · HTTP 401 · retryable: no · since 4.9.2
Message: the device is suspended
What it means. The device is suspended. Sync and channel requests admit suspended devices (they receive commands, not grants); the credential routes (/v2/credentials/*) do not, so a suspended device gets no certificate or principal.
Fix.
1.
Ask whoever suspended it to reinstate it; prorm devices show <id>.
Raised by: klock service (api/klock/lib/device-auth.ts), klock service (api/klock/routes/credentials.ts).

invalid_state#

The device cannot do that in its state. · HTTP — · retryable: no · since 4.9.2
Message: invalid_state: a {status} device cannot be suspended
What it means. A suspend, reinstate or command was asked of a device whose status does not allow it (a revoked or wiped device takes no commands).
Fix.
1.
Check its status: prorm devices show <id>.
Raised by: klock service (api/klock/internal.ts).

kerberos_realm_missing#

The team has no Kerberos realm. · HTTP 409 · retryable: no · since 4.9.2
Message: The team has no Kerberos realm; create it first
What it means. This device’s session is in a team context, and a device principal is issued in the team’s own realm, which the team has not created.
Fix.
1.
A team role with kerberos:manage (owner, admin or security) creates the realm: POST /teams/:teamId/kerberos.
2.
Or issue the principal outside the team context, in your own account.
Raised by: klock service (api/klock/providers/kerberos.ts).

keychain_write_failed#

Could not write to the keychain. · HTTP — · retryable: yes · since 4.9.2
Message: could not write keychain entry {entry}
What it means. The OS keychain refused the write (locked, or no keychain in a headless session).
Fix.
1.
Unlock the keychain (security unlock-keychain) and retry.
2.
On a headless machine, set up keyStore: file (the key then sits in the 0600 file).
Raised by: device agent / klock core (src/klock/agent/devicekey.ts).
Local codes: DeviceKeyError:store-failed.

klock_service_unavailable#

The klock service could not register the device. · HTTP 502 · retryable: yes · since 4.9.2
Message: The klock service could not register the device: {reason}
What it means. The API could not reach, or was refused by, the klock service while opening a device session.
Fix.
1.
Retry prorm login in a moment; check https://status.prod-orm.io.
Raised by: API (api/security/controllers/klock.ts).

pairing_expired#

The pairing code has expired. · HTTP 410 · retryable: no · since 4.9.2
Message: that pairing code has expired; start pairing again on the new device
What it means. A pairing code is good for 10 minutes after the new device shows it.
Fix.
1.
On the new device, start again: prorm login --pair, and approve the new code.
Raised by: klock service (api/klock/internal.ts), API (api/controllers/devices.ts).
Related: pairing_not_found.

pairing_kind_mismatch#

The pairing asked for another kind of session. · HTTP 409 · retryable: no · since 4.9.2
Message: The new device asked for a {kind} session, not {asked}
What it means. The approver chose --kind device (a trusted, lasting device) and the new device asked for interactive, or the reverse. The code is spent.
Fix.
1.
Start again on the new device with the kind you mean (prorm devices pair --kind device\|interactive) and approve with the same --kind.
Raised by: API (api/controllers/devices.ts).
Related: pairing_used.

pairing_not_found#

No pairing has that code. · HTTP 404 · retryable: no · since 4.9.2
Message: no pairing has that code
What it means. The pairing code (or, polling, the pairing id) matches no pairing: it was mistyped, or never issued. A poll signed by another key than the one that started the pairing gets the same answer.
Fix.
1.
Check the code the new device shows (8 characters, like KXQ7-M2PD).
2.
On the new device, start again: prorm login --pair.
Raised by: klock service (api/klock/internal.ts), klock service (api/klock/routes/pair.ts), API (api/controllers/devices.ts).
Related: pairing_expired, pairing_used.

pairing_used#

The pairing code has already been approved. · HTTP 409 · retryable: no · since 4.9.2
Message: that pairing code has already been approved
What it means. A pairing code is approved once. A second approval — by anyone, even the same account — is refused, so a code seen over a shoulder cannot pair a second time.
Fix.
1.
If the new device is not signed in, start again on it: prorm login --pair.
2.
If you did not approve it, review your devices: prorm devices list.
Raised by: klock service (api/klock/internal.ts), API (api/controllers/devices.ts).
Related: pairing_not_found.

provider_unknown#

No such credential provider. · HTTP 404 · retryable: no · since 4.9.2
Message: no credential provider {provider}
What it means. A device asked /v2/credentials/<provider> for a provider the klock service (or the API) does not have. The providers are tls and kerberos.
Fix.
1.
Use prorm klock certs request for a TLS certificate.
2.
Update the CLI: an older one may name a provider that was renamed.
Raised by: klock service (api/klock/lib/credentials.ts), API (api/security/controllers/klockCredentials.ts).

reason_required#

A reason is required. · HTTP 400 · retryable: no · since 4.9.2
Message: Say why: a reason is required (it is kept in the audit log, and the owner is told)
What it means. Acting on someone else's device or session (a team admin, or staff) needs a reason: it goes on their audit trail and into the email they get. Staff reasons are 10–500 characters.
Fix.
1.
Add --reason "…" (the CLI) or fill in the reason (the console).
Raised by: API (api/controllers/devices.ts).

seal_binding_invalid#

The seal binding was refused. · HTTP 400 · retryable: no · since 4.9.2
Message: The seal binding was refused: {reason}
What it means. The sealing key’s binding (signed by the device key) is missing, does not verify, or names another key or device.
Fix.
1.
Retry prorm login; if it persists, upgrade the CLI.
Raised by: API (api/security/controllers/klock.ts), klock service (api/klock/lib/enrolment.ts), klock service (api/klock/lib/trust.ts).

ticket_expired#

The enrolment ticket has expired. · HTTP 401 · retryable: no · since 4.9.2
Message: the enrolment ticket has expired
What it means. Enrolment tickets are short-lived; this one ran out before it was used.
Fix.
1.
Start the sign-in again: prorm login.
Raised by: klock service (api/klock/lib/enrolment.ts), klock service (api/klock/lib/trust.ts).

ticket_invalid#

The enrolment ticket is not valid. · HTTP 401 · retryable: no · since 4.9.2
Message: The enrolment ticket does not verify: {reason}
What it means. The API-signed enrolment ticket does not verify, is for another device key or account, or lacks a thumbprint and a proof of possession.
Fix.
1.
Start the sign-in again: prorm login.
Raised by: API (api/security/controllers/klock.ts), klock service (api/klock/lib/enrolment.ts), klock service (api/klock/lib/trust.ts).
Related: ticket_expired, ticket_used.

ticket_used#

The enrolment ticket has been used. · HTTP 401 · retryable: no · since 4.9.2
Message: this enrolment ticket has been used
What it means. Tickets are single-use.
Fix.
1.
Start the sign-in again: prorm login.
Raised by: klock service (api/klock/lib/enrolment.ts).

tls_delivery_invalid#

The certificate delivery was incomplete. · HTTP — · retryable: yes · since 4.9.2
Message: the delivery carries no certificate
What it means. A tls credential delivery (from the credentials route or sync) had no certificate in it.
Fix.
1.
Run prorm klock sync, or prorm klock certs request.
Raised by: device agent / klock core (src/klock/providers/tls.ts).

tls_key_invalid#

The TLS key or certificate does not fit. · HTTP — · retryable: no · since 4.9.2
Message: the certificate is not for this device’s TLS key
What it means. Locally, the stored TLS key could not be read, there is no pending key for a delivered certificate, or the delivered certificate is not for the key this device holds. Nothing is installed.
Fix.
1.
Request a fresh certificate: prorm klock certs request.
Raised by: device agent / klock core (src/klock/providers/tls.ts).

tls_not_enrolled#

This klock has no enrolled device. · HTTP — · retryable: no · since 4.9.2
Message: this klock has no enrolled device
What it means. A TLS certificate is issued to an enrolled device, and this klock has no device id yet.
Fix.
1.
Sign in first: prorm login (or prorm klock init on a host).
Raised by: device agent / klock core (src/klock/providers/tls.ts).

tls_store_failed#

The keychain refused the TLS key. · HTTP — · retryable: yes · since 4.9.2
Message: the keychain refused the TLS key
What it means. The OS keychain would not store the new TLS private key. The key is not written anywhere else for a keychain-backed device.
Fix.
1.
Unlock the keychain and run the command again.
Raised by: device agent / klock core (src/klock/providers/tls.ts).

transfer_expired#

The transfer has expired. · HTTP 410 · retryable: no · since 4.9.2
Message: the transfer has expired
What it means. A transfer lives 24 hours on the relay. This one was not accepted and completed in time, so its encrypted chunks were deleted.
Fix.
1.
Ask the sender to send it again with prorm klock cp.
Raised by: klock service (api/klock/routes/transfers.ts).
Related: transfer_not_found.

transfer_not_found#

No such transfer. · HTTP 404 · retryable: no · since 4.9.2
Message: no such transfer
What it means. The klock service has no transfer with that id that this device is an end of. Only the sending device and the receiving device see a transfer — any other device, including your own others, gets this same answer — and the recipient sees it only once the sender has finished uploading it.
Common causes.
A typo in the id, or an id from another device’s inbox.
The sender has not finished prorm klock cp yet.
Running prorm klock accept on the sending device.
Fix.
1.
Run prorm klock inbox on the receiving device for the ids waiting there.
2.
On the sending device, prorm klock inbox --sent lists what it sent.
Raised by: klock service (api/klock/routes/transfers.ts).
Related: transfer_expired.

transfer_sender_revoked#

The sending device is no longer trusted. · HTTP 410 · retryable: no · since 4.9.2
Message: the sending device is no longer trusted; the transfer was cancelled
What it means. The device that sent this transfer has since been suspended, revoked or wiped, so nothing it sent is delivered. The transfer is cancelled and its chunks deleted.
Fix.
1.
Ask the sender to send it again from a trusted device.
2.
If you did not expect the sender to be revoked, check prorm devices list and your security events.
Raised by: klock service (api/klock/routes/transfers.ts).
Related: device_revoked, device_suspended.

unknown_device#

No device is enrolled with this key (internal). · HTTP 401 · retryable: no · since 4.9.2
Message: no device is enrolled with this key
What it means. Logged by the klock service only: it has no device for the signing key’s thumbprint (never enrolled, or its enrolment was removed). Callers get bad_signature, so enrolment cannot be probed.
Fix.
1.
Enrol this device: prorm login.
Raised by: klock service (api/klock/lib/device-auth.ts).
Related: device_revoked, bad_signature.

Sync#

command_invalid#

A device command does not verify. · HTTP — · retryable: no · since 4.9.2
Message: the command does not verify: {reason}
What it means. A command (logout, wipe, rotate-key, resync) is not API-signed for this device. The agent refuses it and reports it.
Fix.
1.
Nothing to do on the device; report it if it repeats.
Raised by: klock service (api/klock/lib/trust.ts).

feed_invalid#

The revocation feed does not verify. · HTTP — · retryable: yes · since 4.9.2
Message: the revocation feed does not verify: {reason}
What it means. The API’s revocation feed, mirrored by the klock service, is missing, malformed or not signed by the keyset.
Fix.
1.
Retry later; report it if it persists.
Raised by: klock service (api/klock/lib/trust.ts), MCP Worker (workers/mcp/src/auth.ts).

sync_bad_envelope#

The sync answer does not verify. · HTTP — · retryable: yes · since 4.9.2
Message: the sync answer does not verify: {reason}
What it means. The sync answer is not a JWS signed by the klock service’s published key, has no syncSeq, or there is no verified keyset to check it with.
Fix.
1.
Run prorm klock sync again; if it persists, prorm login.
Raised by: device agent / klock core (src/klock/agent/sync.ts), device agent / klock core (src/klock/agent/index.ts).
Local codes: SyncError:bad-envelope.

sync_bad_grant#

The synced grant does not verify. · HTTP — · retryable: no · since 4.9.2
Message: the synced grant does not verify: {reason}
What it means. The grant in the sync answer does not verify, or is for another issuer, session or device.
Fix.
1.
Sign in again: prorm login.
Raised by: device agent / klock core (src/klock/agent/sync.ts).
Local codes: SyncError:bad-grant.

sync_http#

klock sync was refused. · HTTP — · retryable: no · since 4.9.2
Message: klock sync answered {status} ({code})
What it means. The klock service answered the sync with an error; the code in brackets is the service’s and has its own entry.
Fix.
1.
Look up the code in brackets on this page and follow its fix.
Raised by: device agent / klock core (src/klock/agent/sync.ts).
Local codes: SyncError:http.

sync_network#

klock sync could not reach the service. · HTTP — · retryable: yes · since 4.9.2
Message: klock sync failed: {reason}
What it means. The sync request did not get an answer (offline, DNS, proxy, timeout).
Fix.
1.
Check the connection, then prorm klock sync. Until checkInBy, the session keeps working offline.
Raised by: device agent / klock core (src/klock/agent/sync.ts).
Local codes: SyncError:network.

sync_no_device#

Nothing to sync with. · HTTP — · retryable: no · since 4.9.2
Message: the klock has no device to sync
What it means. The klock has no enrolled device (a v1 file, or a local klock), so there is nothing to sync.
Fix.
1.
Sign in with a device session: prorm login, or upgrade a v1 file with prorm klock upgrade.
Raised by: device agent / klock core (src/klock/agent/sync.ts), device agent / klock core (src/klock/agent/index.ts).
Local codes: SyncError:no-device.

sync_nonce_mismatch#

The sync answer is not for this request. · HTTP — · retryable: yes · since 4.9.2
Message: the sync answer is not for this request (replayed?)
What it means. The answer’s echoNonce is not the nonce this request sent — an old answer replayed.
Fix.
1.
Run prorm klock sync again on a trusted network.
Raised by: device agent / klock core (src/klock/agent/sync.ts).
Local codes: SyncError:nonce-mismatch.

sync_response_rollback#

The sync answer is older than one already seen. · HTTP — · retryable: no · since 4.9.2
Message: the sync answer's syncSeq {seq} is lower than {seen} (rollback)
What it means. The client got a sync answer (or grant) with a lower sequence than it has already seen: a replayed or rolled-back response. The agent records the finding klock.sync-rollback.
Fix.
1.
Run prorm klock sync again on a trusted network.
2.
If it repeats, report it: it can mean an interfering proxy.
Raised by: device agent / klock core (src/klock/agent/sync.ts).
Local codes: SyncError:rollback.
Related: sync_rollback.

sync_rollback#

The device is behind what it acknowledged. · HTTP 409 · retryable: no · since 4.9.2
Message: syncSeq {seq} is behind what this device has acknowledged ({ack})
What it means. The device’s syncSeq is lower than one it already acknowledged: its klock was restored from a backup or copied from an older snapshot.
Fix.
1.
Sign in again to reset the device state: prorm login.
Raised by: klock service (api/klock/routes/sync.ts).
Related: sync_seq_ahead, sync_response_rollback.

sync_seq_ahead#

The device claims a sync that never happened. · HTTP 409 · retryable: no · since 4.9.2
Message: syncSeq {seq} is ahead of anything issued ({issued})
What it means. The device’s syncSeq is higher than any the service issued — the klock was edited, or belongs to another deployment.
Fix.
1.
Sign in again: prorm login.
Raised by: klock service (api/klock/routes/sync.ts).

Signatures and cryptography#

bad_digest#

Content-Digest does not match the body. · HTTP 401 · retryable: no · since 4.9.2
Message: Content-Digest does not match the body
What it means. The body that arrived is not the body that was signed.
Fix.
1.
Check for a proxy or middleware that re-encodes JSON bodies, then retry.
Raised by: klock service (api/klock/lib/device-auth.ts).
Local codes: HttpSigError:bad-digest.
Related: signature_invalid.

bad_nonce#

Not a nonce. · HTTP 400 · retryable: no · since 4.9.2
Message: bad_nonce
What it means. The API's DeviceGuard Durable Object was asked to claim a nonce that is not 16–64 base64url characters. It is internal to the API.
Fix.
1.
Report it: the API validates nonces before this point.
Raised by: API (api/sockets/device-guard.ts).

bad_signature#

The request signature does not verify. · HTTP 401 · retryable: no · since 4.9.2
Message: the signature does not verify against an enrolled device key
What it means. The klock service could not verify the device signature, or no device is enrolled with the signing key. The two are deliberately indistinguishable, so the answer never reveals whether a key is enrolled.
Fix.
1.
Run prorm klock sync; if it fails, prorm login to enrol again.
Raised by: klock service (api/klock/lib/device-auth.ts).
Local codes: HttpSigError:bad-signature.
Related: signature_invalid, device_key_mismatch.

canonical_json_invalid#

Not canonical JSON. · HTTP — · retryable: no · since 4.9.2
Message: non-integer number {n}
What it means. klock signs canonical JSON (an RFC 8785 subset): integers only in the safe range, no lone surrogates, at most 64 levels, no undefined. The value could not be encoded or parsed under those rules.
Fix.
1.
Pass integers (seconds, not milliseconds with fractions) and plain JSON values.
2.
If a server document fails, report it: both sides share test vectors.
Raised by: device agent / klock core (src/klock/canonical.ts), outh (Go) (outh/internal/canon/canon.go).
Local codes: CanonicalJsonError.

clock_skew#

The clock is too far off. · HTTP 401 · retryable: yes · since 4.9.2
Message: The request was signed too far from the server's time
What it means. A signed request’s created is more than 60 seconds from the server’s clock. The answer carries Klock-Server-Time; the CLI adopts that offset and retries once automatically, so you see this only when the retry fails too.
Fix.
1.
Sync the system clock: sudo sntp -sS time.apple.com (macOS) or timedatectl set-ntp true (Linux).
2.
Run the command again.
Raised by: API (api/security/controllers/klock.ts), klock service (api/klock/lib/device-auth.ts), MCP Worker (workers/mcp/src/auth.ts).
Local codes: HttpSigError:clock-skew.
Related: signature_expired, rpc_clock_skew.

csr_attestation_invalid#

The device key did not vouch for this certificate key. · HTTP 401 · retryable: no · since 4.9.2
Message: csrAttestation is not the device key's signature over the CSR key
What it means. Every certificate request carries the device’s Ed25519 signature over the SHA-256 of the new key (klock/csr/v1). It is checked against the enrolled device key by klock, and again by the API against the session’s key. Here it did not verify: a different device key, a different CSR key, or a tampered request.
Fix.
1.
Run prorm klock certs request again from the device itself.
2.
If it keeps failing, check prorm klock verify: the device key may not be this klock’s.
Raised by: klock service (api/klock/providers/tls.ts), API (api/security/controllers/klockCredentials.ts).
Related: device_key_mismatch.

csr_invalid#

The certificate request is malformed. · HTTP 400 / 422 · retryable: no · since 4.9.2
Message: csr is one PEM CERTIFICATE REQUEST
What it means. The CSR is not a single PEM PKCS#10 request, its self-signature does not verify, it asks for extensions other than the subject alternative name, or its validity is out of range. It is checked by the klock service, the API and the authority.
Fix.
1.
Let the CLI build it: prorm klock certs request.
2.
If you build CSRs yourself, see the TLS section of docs/guides/klock.md.
Raised by: klock service (api/klock/providers/tls.ts), API (api/security/controllers/klockCredentials.ts).
Related: csr_key_type, csr_subject_mismatch.

csr_key_type#

The certificate key must be P-256. · HTTP 400 / 422 · retryable: no · since 4.9.2
Message: the TLS key must be P-256 ECDSA
What it means. Device certificates are for ECDSA P-256 keys only: Cloudflare’s mTLS and common TLS stacks do not take Ed25519 client certificates. RSA, other curves and Ed25519 are refused.
Fix.
1.
Let the CLI make the key: prorm klock certs request.
Raised by: klock service (api/klock/providers/tls.ts), API (api/security/controllers/klockCredentials.ts).
Related: csr_invalid.

csr_subject_mismatch#

The certificate request names something else. · HTTP 400 / 422 · retryable: no · since 4.9.2
Message: the CSR does not name this device
What it means. The authority signs only CN=device/<deviceId> with exactly one URI name urn:prorm:device:<deviceId>, for the key the device attested. This CSR names another device, carries other names (DNS, IP, email, extra subject fields), or is for a different key than spki.
Fix.
1.
Let the CLI build the request for this device: prorm klock certs request.
Raised by: API (api/security/controllers/klockCredentials.ts).
Related: csr_invalid, csr_attestation_invalid.

jws_bad_alg#

The JWS is not EdDSA. · HTTP — · retryable: no · since 4.9.2
Message: alg must be EdDSA, not {alg}
What it means. klock accepts Ed25519 (EdDSA) signatures only; anything else is refused before any key is looked up.
Fix.
1.
Use a token issued by the prorm API (prorm login, prorm klock sync).
Raised by: device agent / klock core (src/klock/jws.ts), outh (Go) (outh/internal/klockv2/jws.go).
Local codes: JwsError:bad-alg.

jws_bad_header#

The JWS header is not allowed. · HTTP — · retryable: no · since 4.9.2
Message: unexpected header member {name}
What it means. The JWS header is not strict JSON, is not an object, lacks kid, or has members beyond alg, kid and typ.
Fix.
1.
Run prorm klock sync.
2.
If it persists, the token was not made by prorm: sign in again with prorm login.
Raised by: device agent / klock core (src/klock/jws.ts), outh (Go) (outh/internal/klockv2/jws.go).
Local codes: JwsError:bad-header.

jws_bad_payload#

The JWS payload is not what it should be. · HTTP — · retryable: no · since 4.9.2
Message: not a klock v2 grant: {why}
What it means. The payload is not strict JSON, or does not have the shape the document type requires.
Fix.
1.
Run prorm klock sync; if it persists, prorm login.
Raised by: device agent / klock core (src/klock/jws.ts), outh (Go) (outh/internal/klockv2/grant.go).
Local codes: JwsError:bad-payload.

jws_bad_signature#

The JWS signature does not verify. · HTTP — · retryable: no · since 4.9.2
Message: the signature does not verify
What it means. The document was changed after it was signed, or was signed by another key with the same kid. Locally this is treated as tampering.
Fix.
1.
Run prorm klock sync.
2.
If that fails, prorm login.
Raised by: device agent / klock core (src/klock/jws.ts), outh (Go) (outh/internal/klockv2/jws.go).
Local codes: JwsError:bad-signature.
Related: klock_tampered, grant_invalid.

jws_bad_typ#

The JWS is the wrong type. · HTTP — · retryable: no · since 4.9.2
Message: typ must be {expected}, not {typ}
What it means. Each klock document has its own typ (grant, device certificate, sync envelope, ticket, command); one kind was presented where another is required.
Fix.
1.
Present the right document; for a grant, run prorm klock sync for a fresh one.
Raised by: device agent / klock core (src/klock/jws.ts), outh (Go) (outh/internal/klockv2/jws.go).
Local codes: JwsError:bad-typ.

jws_malformed#

Not a compact JWS. · HTTP — · retryable: no · since 4.9.2
Message: a compact JWS has three parts
What it means. A grant, certificate, envelope or ticket is not a compact JWS: the wrong number of parts, non-base64url parts, or a signature that is not 64 bytes.
Fix.
1.
Run prorm klock sync to fetch a fresh copy.
2.
If it persists, sign in again: prorm login.
Raised by: device agent / klock core (src/klock/jws.ts), outh (Go) (outh/internal/klockv2/jws.go).
Local codes: JwsError:malformed.
Related: grant_invalid.

jws_unknown_kid#

Signed by a key this client does not know. · HTTP — · retryable: yes · since 4.9.2
Message: no key for kid {kid}
What it means. The signing key id is not in the verified keyset this client holds. After a key rotation the keyset is refreshed on the next sync.
Fix.
1.
Run prorm klock sync online to refresh the keyset.
2.
If the kid is still unknown, the token is not from this API: sign in again.
Raised by: device agent / klock core (src/klock/jws.ts), outh (Go) (outh/internal/klockv2/jws.go).
Local codes: JwsError:unknown-kid.
Related: keyset_invalid, no_keyset.

keytab_invalid#

The delivered keytab is not this principal’s. · HTTP — · retryable: no · since 4.9.2
Message: keytab: {reason}
What it means. A sealed keytab opened, but what is inside is not an MIT keytab (format 0x0502) holding exactly the principal and the kvno the klock names — for example a keytab left from before a rotation, one for another principal, or a damaged one.
Common causes.
The key was rotated (a new kvno) and this file still holds the older keytab.
The klock file was edited, or restored from a backup.
Fix.
1.
Run prorm klock sync to receive the current keytab.
2.
If it persists, run prorm klock kerberos rotate for a new key.
Raised by: device agent / klock core (src/klock/providers/kerberos.ts), outh (Go) (outh/internal/klockv2/keytab.go), klock service (api/klock/providers/kerberos.ts).
Local codes: KeytabError:keytab_invalid.
Related: seal_auth_failed, seal_invalid.

nonce_replayed#

That signed request was already used. · HTTP 401 · retryable: yes · since 4.9.2
Message: That signed request was already used
What it means. Nonces are single-use for 120 s per device key on unsafe methods, admin capabilities and MCP-forwarded intents. The same signed request arrived twice — a replay, or a client that resent without re-signing.
Fix.
1.
Run the command again (the CLI signs afresh on every attempt).
2.
If you did not resend it, someone may be replaying your requests: prorm sessions and revoke anything unknown.
Raised by: API (api/security/controllers/klock.ts).
Related: nonce_reused, rpc_replay.

nonce_reused#

The klock service has seen this request. · HTTP 401 · retryable: yes · since 4.9.2
Message: this request has been seen before
What it means. The klock service's twin of nonce_replayed: a sync or channel request reused a nonce.
Fix.
1.
Run prorm klock sync again.
Raised by: klock service (api/klock/routes/sync.ts), klock service (api/klock/worker.ts).
Related: nonce_replayed.

seal_auth_failed#

The sealed box does not open. · HTTP — · retryable: no · since 4.9.2
Message: AES-GCM: authentication failed
What it means. The box was sealed to another device key or context, or its bytes changed.
Common causes.
The device key was rotated after the secret was sealed.
The klock file was copied from another machine.
Fix.
1.
Run prorm klock sync so the server seals the secret to this device again.
2.
If the device was re-enrolled, re-issue the credential.
Raised by: device agent / klock core (src/klock/crypto.ts), outh (Go) (outh/internal/klockv2/seal.go).

seal_invalid#

Not a klock-seal-v1 box. · HTTP — · retryable: no · since 4.9.2
Message: malformed sealed box
What it means. A sealed secret (keytab, database secret or file key) is not a {"v":1,"epk","n","ct"} box, has extra members, or names a low-order X25519 key.
Fix.
1.
Run prorm klock sync to receive the credential again.
Raised by: device agent / klock core (src/klock/seal.ts), outh (Go) (outh/internal/klockv2/seal.go).
Related: seal_auth_failed.

signature_expired#

The request signature has expired. · HTTP 401 · retryable: yes · since 4.9.2
Message: the signature has expired
What it means. Signatures live 60 seconds (expires). The request was held too long before it arrived, or the clock is off.
Fix.
1.
Retry: the CLI signs afresh on every attempt.
2.
If it keeps happening, sync the system clock (NTP).
Raised by: klock service (api/klock/lib/device-auth.ts).
Local codes: HttpSigError:expired.
Related: clock_skew.

signature_incomplete#

The signature does not cover what it must. · HTTP 401 · retryable: no · since 4.9.2
Message: the signature must cover {component}
What it means. The signature omits a required component (@method, @authority, @path, @query, content-digest, authorization, klock-client, and idempotency-key / x-prorm-team when present).
Fix.
1.
Upgrade the CLI; do not add signed headers after signing.
Raised by: klock service (api/klock/lib/device-auth.ts).
Local codes: HttpSigError:missing-component.
Related: signature_invalid.

signature_invalid#

The request signature was refused. · HTTP 401 · retryable: no · since 4.9.2
Message: The request signature was refused: {reason}
What it means. The API could not verify the RFC 9421 signature on a Authorization: Klock request: a component is missing, the digest does not match the body, the key is not the grant’s device key, or the signature does not verify. The klock service reports the same failures with finer codes (bad_signature, bad_digest, signature_malformed, …).
Common causes.
A proxy rewrote a signed header or the body.
The request was signed by a key other than the grant’s device key.
Fix.
1.
Retry once; if it persists, run prorm klock sync.
2.
Make sure no proxy rewrites the body, path or Authorization header.
3.
If it still fails, sign in again: prorm login.
Raised by: API (api/security/controllers/klock.ts), MCP Worker (workers/mcp/src/auth.ts).
Related: bad_signature, clock_skew, device_key_mismatch.

signature_malformed#

The request signature is malformed. · HTTP 401 · retryable: no · since 4.9.2
Message: the signature keyid is not a device thumbprint
What it means. The Signature-Input / Signature headers do not parse, carry unexpected parameters, or lack the klock-v2 tag.
Fix.
1.
Upgrade the CLI (npm i -g ts-prorm-orm@latest); an old or third-party signer produced it.
Raised by: klock service (api/klock/lib/device-auth.ts).
Local codes: HttpSigError:malformed, HttpSigError:bad-params, HttpSigError:bad-tag.
Related: signature_invalid.

transfer_chunk_corrupt#

A stored chunk was altered. · HTTP 502 · retryable: no · since 4.9.2
Message: the chunk on the relay is not the one the sender stored
What it means. The relay records the length and SHA-256 of each sealed chunk when it arrives, and checks them again before serving it. This one no longer matches, so it is not relayed (the recipient’s AES-GCM check would refuse it too). It is recorded as an alert.
Fix.
1.
Refuse the transfer (prorm klock refuse <id>) and ask the sender to send it again.
2.
Report it to support: an object changed in the relay bucket.
Raised by: klock service (api/klock/lib/transfer-store.ts).

transfer_key_invalid#

The sealed file key is malformed. · HTTP 400 · retryable: no · since 4.9.2
Message: wrappedKey is not a sealed 32-byte key
What it means. Completing a transfer needs the file key sealed to the recipient (klock-seal-v1: a 32-byte ephemeral key, a 12-byte nonce and a 48-byte ciphertext). The relay cannot open it, but it refuses one that has the wrong shape.
Fix.
1.
Send again with prorm klock cp.
Raised by: klock service (api/klock/routes/transfers.ts).
Related: transfer_manifest_sig_invalid, seal_invalid.

transfer_manifest_sig_invalid#

The file list is not signed by this device. · HTTP 400 · retryable: no · since 4.9.2
Message: the manifest signature does not verify
What it means. Completing a transfer needs the file list signed by the sending device’s key (a klock-manifest+jws over the transfer id and the manifest exactly as offered). The signature did not verify, was by another key, or covered another list or transfer. It is recorded as a tamper event.
Fix.
1.
Send again with prorm klock cp; if it happens again, run prorm klock verify.
Raised by: klock service (api/klock/routes/transfers.ts).
Related: transfer_key_invalid.

unsigned#

The request is not klock-signed. · HTTP 401 · retryable: no · since 4.9.2
Message: the request is not klock-signed: {reason}
What it means. The klock service accepts only device-signed requests, with Authorization: Klock <grant> or Klock device=<thumbprint>.
Fix.
1.
Use the CLI or device agent, which sign every request.
2.
Sign in so there is a device key: prorm login.
Raised by: klock service (api/klock/lib/device-auth.ts).
Related: signature_malformed.

The .klock file#

klock_coordinates_missing#

The .klock does not say which database or session. · HTTP — · retryable: no · since 4.5.0
Message: the .klock does not say which {missing}; pass --{flags}
What it means. The file lacks databaseId, sessionId or role, for example because outh wrote it or rewrote a prorm file.
Fix.
1.
Pass the flags (--database --session --role), or $OUTH_DATABASE / $OUTH_SESSION_ID.
2.
Or re-issue with prorm passwordless issue / prorm roles grant.
Raised by: CLI (src/cli/basic/commands/passwordless.ts), library (src/store-key.ts).

klock_format_invalid#

The .klock is not a valid klock. · HTTP — · retryable: no · since 4.5.0
Message: {path}: {reason}
What it means. The file does not parse as a klock: it is not JSON, a field has the wrong type, or a v2 field (device, session, integrity) breaks the schema in src/klock/klock-file.schema.json.
Common causes.
The file was hand-edited or truncated.
Another tool wrote something else at that path.
Fix.
1.
Run prorm klock show <path> to see what is wrong.
2.
Restore the file from where it was issued, or re-issue it (prorm passwordless issue, prorm login for a device session).
Raised by: device agent / klock core (src/klock/format.ts), device agent / klock core (src/klock/agent/store.ts), library (src/klock-io.ts), outh (Go) (outh/internal/klock/format.go).
Local codes: KlockStoreError:format, KlockFileError:format, KlockFormatError.
Related: klock_version_unsupported.

klock_io_failed#

The .klock could not be read or written. · HTTP — · retryable: yes · since 4.9.2
Message: cannot read {path}: {reason}
What it means. The file exists but reading or writing it failed at the operating system, or the integrity key needed to tag a keychain-backed klock is not in the keychain.
Fix.
1.
Check the file and directory permissions and free disk space.
2.
On macOS, unlock the login keychain (security unlock-keychain) and try again.
Raised by: device agent / klock core (src/klock/agent/store.ts).
Local codes: KlockStoreError:io.

klock_mode_insecure#

The .klock is readable by others. · HTTP — · retryable: no · since 4.5.0
Message: {path} is mode {mode}; it must be 0600
What it means. The file has group or other permission bits. A .klock holds a secret (v1) or names a device key (v2), so every reader refuses a file anyone but the owner can read.
Fix.
1.
Run chmod 600 <path>.
2.
If others could read it, treat it as leaked: revoke it (prorm passwordless revoke <session>, or prorm devices revoke <id> for a device) and re-issue.
Raised by: device agent / klock core (src/klock/agent/store.ts), library (src/klock-io.ts), outh (Go) (outh/internal/klock/klock.go).
Local codes: KlockStoreError:mode, KlockFileError:mode.

klock_not_found#

No .klock at the path. · HTTP — · retryable: no · since 4.5.0
Message: No .klock at {path}.
What it means. Nothing is at the resolved path. The path comes from --klock, then $OUTH_KLOCK, then ./.klock (for a profile klock, ~/.prorm/klock/<profile>.klock).
Common causes.
The command ran in another directory than the one holding ./.klock.
$OUTH_KLOCK points at an old location.
The session was never issued on this machine.
Fix.
1.
Check --klock, then $OUTH_KLOCK, then ./.klock.
2.
Issue one: prorm passwordless issue --database <id> --read (a cloud session) or prorm db init (a local database).
3.
For a v2 device session, sign in again: prorm login.
Raised by: device agent / klock core (src/klock/agent/store.ts), library (src/klock-io.ts), outh (Go) (outh/internal/klock/klock.go).
Local codes: KlockStoreError:not-found, KlockFileError:missing.
Related: klock_path_invalid.

klock_overwrite_refused#

Refusing to overwrite a device identity. · HTTP — · retryable: no · since 4.9.2
Message: {path} holds a klock of kind {kind} (a device identity); write this one elsewhere with --klock <file>
What it means. passwordless issue, roles grant or db init would have overwritten a version 2 device identity or a klock sealed with an integrity tag.
Fix.
1.
Pass --klock with another path.
Raised by: CLI (src/cli/basic/commands/passwordless.ts).

klock_path_invalid#

The klock path cannot be resolved. · HTTP — · retryable: no · since 4.9.2
Message: a profile name is letters, digits, '.', '_' and '-': {name}
What it means. The path or profile name given for the klock cannot name a file: - was given where a file must be read, ~ has no home directory to expand to, or a profile name has characters outside [A-Za-z0-9._-].
Fix.
1.
Pass a real file path with --klock <file>.
2.
Use a profile name of letters, digits, ., _ and -.
3.
Set $HOME when running in a container or service account without one.
Raised by: device agent / klock core (src/klock/path.ts), outh (Go) (outh/internal/klock/path.go).
Related: klock_not_found.

klock_read_only#

Refusing to write a newer klock. · HTTP — · retryable: no · since 4.9.2
Message: refusing to write a version {version} klock
What it means. The file is a version this build can read but not write. Writing it would drop fields this build does not know.
Fix.
1.
Upgrade the CLI, or write the new klock elsewhere with --klock <file>.
Raised by: device agent / klock core (src/klock/format.ts), device agent / klock core (src/klock/agent/store.ts), outh (Go) (outh/internal/klock/write.go).
Local codes: KlockStoreError:read-only.

klock_secret_length#

The secret is the wrong length. · HTTP — · retryable: no · since 4.5.0
Message: a local klock secret is 32 bytes; this one is {length}
What it means. A session secret is 32 bytes; readers accept 16–64 and warn under 32. This one is outside that range, or writeKlock was handed a secret that is not exactly 32 bytes.
Common causes.
The file was truncated or hand-edited.
An environment variable holding the secret was unset or a placeholder.
$OUTH_SESSION_SECRET was not the secret the issue response returned.
Fix.
1.
Re-issue the session (prorm passwordless issue) or re-run prorm db init for a 32-byte secret.
2.
For outh, set $OUTH_SESSION_SECRET to the exact secret, or unset it so outh keeps its own.
Raised by: library (src/local-klock.ts), library (src/store-key.ts), library (src/transfer/transfer-klock.ts), CLI (src/cli/basic/commands/passwordless.ts), outh (Go) (outh/internal/klock/klock.go).

klock_secret_missing#

The .klock holds no secret. · HTTP — · retryable: no · since 4.5.0
Message: {path} holds no secret
What it means. The secret field is empty or missing. A version 2 service klock issued without a v1-compatible secret signs with its device key, which some readers do not do yet.
Fix.
1.
Re-issue the session: the secret cannot be recovered from the server.
2.
For a v2 service session, use a client that signs with the device key.
Raised by: library (src/local-klock.ts), library (src/store-key.ts), library (src/transfer/transfer-klock.ts), device agent / klock core (src/klock/format.ts), outh (Go) (outh/internal/klock/klock.go).
Related: klock_secret_length.

klock_secret_ref_unresolved#

The database password named by urlSecretRef is not available. · HTTP — · retryable: no · since 4.6.6
Message: {path}: the database password is not in the file (urlSecretRef {ref})
What it means. A local klock's url needs its password from urlSecretRef (env:NAME or keychain:<service>/<account>), and neither the environment, the .env beside the klock, nor this machine's keychain has it.
Common causes.
Only the klock was mounted into a container, not its .env.
Fix.
1.
Set the variable in the gate’s environment, or mount the .env that prorm db init wrote beside the klock.
2.
For a keychain reference, run the gate on the machine whose keychain holds it.
Raised by: library (src/klock-io.ts).
Local codes: KlockFileError:secret-ref.

klock_tampered#

The .klock was edited or copied. · HTTP — · retryable: no · since 4.9.2
Message: the klock integrity tag does not match (the file was edited)
What it means. A keychain-backed klock v2 carries an HMAC integrity tag over its unsigned fields, and the device key in the keychain must match the file's public key. A mismatch is treated as tampering: the file is used as if it had no session, one klock sync is tried, and the finding klock.tamper-detected is reported at the next sync.
Common causes.
The file was hand-edited (for example its api URL).
The file was copied from another machine, whose keychain holds the real key.
The keychain entry was deleted.
Fix.
1.
Run prorm klock sync; the server re-issues the grant if the session and device key are still valid.
2.
If that fails, sign in again: prorm login.
3.
If you did not edit the file, check prorm devices list for devices you do not recognise and revoke them.
Raised by: device agent / klock core (src/klock/agent/store.ts), device agent / klock core (src/klock/agent/devicekey.ts), device agent / klock core (src/klock/agent/index.ts).
Local codes: DeviceKeyError:mismatch.
Related: grant_invalid, device_key_mismatch.

klock_version_unsupported#

The .klock is a newer version. · HTTP — · retryable: no · since 4.5.0
Message: {path} is version {version}; this build understands versions 1 and 2
What it means. The file's version is newer than this build understands, or missing. prorm klock show still shows a newer file, read-only.
Fix.
1.
Upgrade the CLI or library: npm i -g ts-prorm-orm@latest.
2.
Or re-issue the file with the version this build writes.
Raised by: library (src/klock-io.ts), outh (Go) (outh/internal/klock/klock.go).
Local codes: KlockFileError:version.
Related: klock_read_only.

klock_wrong_kind#

The wrong kind of klock. · HTTP — · retryable: no · since 4.6.6
Message: {path} is a klock of kind {kind}, not a database session
What it means. The file is a klock, but not the kind this reader needs: a CLI device identity where a database session was expected, a cloud session where a local gate klock was expected, or the reverse.
Fix.
1.
Point --klock (or StoreKey.fromKlock) at the database session’s own .klock.
2.
For LocalKlockGate / prorm db serve, use the file prorm db init wrote. A cloud .klock belongs to StoreKey.
Raised by: library (src/klock-io.ts), library (src/local-klock.ts), library (src/store-key.ts), CLI (src/cli/basic/commands/passwordless.ts).
Local codes: KlockFileError:kind.

The local gate#

gate_auth_refused#

The gate refused the token. · HTTP 401 · retryable: no · since 4.7.1
Message: present a valid klock token: Authorization: Klock <token>
What it means. The local gate’s token check failed; the body’s reason says why (missing, not valid, expired, not yet valid, already used).
Fix.
1.
Make a fresh token for every request (LocalKlock.token()).
2.
Sync the clock.
Raised by: library (src/local-klock.ts).
Local codes: GateRefusedError:auth.
Related: gate_token_expired, gate_token_replayed, gate_token_invalid.

gate_query_failed#

The query failed. · HTTP 500 · retryable: no · since 4.7.1
Message: the query failed; the gate logged why
What it means. The database engine behind the local gate refused or failed the statement. The gate logs the engine’s message and does not return it, so a client learns nothing about the schema (PRORM-SA-2026-109).
Fix.
1.
Read the gate’s log (the terminal running prorm db serve) for the engine’s message.
2.
In development only, start the gate with exposeErrors: true to get the message in the response.
Raised by: library (src/local-klock.ts).

gate_scope_refused#

Outside the gate’s scope. · HTTP 403 · retryable: no · since 4.7.1
Message: refused: this gate does not permit writes
What it means. The SQL is outside the gate klock’s scope (ops or tables), or which tables it touches cannot be told.
Fix.
1.
Ask for less, or widen scope in the gate’s klock and restart prorm db serve.
Raised by: library (src/local-klock.ts), library (src/local-klock-scope.ts).
Local codes: GateRefusedError:scope.

gate_token_expired#

The token expired. · HTTP 401 · retryable: yes · since 4.7.1
Message: refused: the token expired
What it means. The token is older than the previous window, usually because the client clock is slow.
Fix.
1.
Sync the clock and make a fresh token.
Raised by: library (src/local-klock.ts).

gate_token_invalid#

The token is not valid. · HTTP 401 · retryable: no · since 4.7.1
Message: refused: the token is not valid
What it means. The token is not from this gate’s secret, or is malformed.
Fix.
1.
Use the client klock that belongs to this gate (prorm db init writes both).
Raised by: library (src/local-klock.ts).

gate_token_missing#

No token. · HTTP 401 · retryable: no · since 4.7.1
Message: refused: no token
What it means. The request to the gate had no Authorization: Klock <token>.
Fix.
1.
Send Authorization: Klock <token> from LocalKlock.token().
Raised by: library (src/local-klock.ts).

gate_token_not_yet_valid#

The token is for a later window. · HTTP 401 · retryable: yes · since 4.7.1
Message: refused: the token is for a window not yet started
What it means. The client clock is ahead of the gate’s.
Fix.
1.
Sync the clock.
Raised by: library (src/local-klock.ts).

gate_token_replayed#

The token has already been used. · HTTP 401 · retryable: yes · since 4.7.1
Message: refused: the token has already been used
What it means. Tokens are single-use: a session id is admitted once per window.
Fix.
1.
Make a fresh token for every request.
Raised by: library (src/local-klock.ts).

Configuration and keys#

authority_unavailable#

The certificate authority could not sign. · HTTP 502 / 503 · retryable: yes · since 4.9.2
Message: The certificate authority could not sign
What it means. The API could not reach the Kerberos/CA authority (KERBEROS_AUTHORITY_URL/KERBEROS_AUTHORITY_TOKEN), or the authority answered with something the API refused to bind (a certificate for another key or subject).
Fix.
1.
Try again shortly.
2.
Operators: check the authority’s /healthz and the API’s KERBEROS_AUTHORITY_* settings.
Raised by: klock service (api/klock/providers/tls.ts), klock service (api/klock/lib/credentials.ts), API (api/security/controllers/klockCredentials.ts).

crypto_unavailable#

No cryptography available. · HTTP — · retryable: no · since 4.9.2
Message: klock: no cryptography available (neither node:crypto nor WebCrypto)
What it means. The runtime has neither node:crypto nor WebCrypto with Ed25519 and X25519.
Fix.
1.
Run on Node 20 or later, or a runtime with WebCrypto Ed25519/X25519 (Workers, current browsers).
Raised by: device agent / klock core (src/klock/crypto.ts).

keyset_invalid#

The keyset does not verify. · HTTP — · retryable: yes · since 4.9.2
Message: the API's keyset does not verify: {reason}
What it means. The keyset is not signed by a pinned root, has expired, lives over 90 days, is issued in the future, has duplicate kids, or has no keys.
Fix.
1.
Run prorm klock sync later; upgrade the CLI if the roots were rotated.
Raised by: device agent / klock core (src/klock/keys.ts), klock service (api/klock/lib/trust.ts), MCP Worker (workers/mcp/src/auth.ts).
Local codes: KeysetError.
Related: keyset_rollback.

keyset_rollback#

The keyset is older than one already seen. · HTTP — · retryable: no · since 4.9.2
Message: keyset seq {seq} is older than {minSeq} (rollback)
What it means. The keyset’s seq is lower than one already verified: an old keyset replayed, which could re-admit a retired key.
Fix.
1.
Retry on a trusted network; report it if it persists.
Raised by: device agent / klock core (src/klock/keys.ts), klock service (api/klock/lib/trust.ts).

klock_key_unpublished#

The klock service key is not in the keyset. · HTTP — · retryable: no · since 4.9.2
Message: the keyset does not publish klock key {kid}
What it means. The klock service signs sync envelopes with a key the published keyset does not list.
Fix.
1.
Operators: publish a keyset containing KLOCK_SERVICE_KID, or fix the kid.
Raised by: klock service (api/klock/lib/trust.ts).

klock_roots_invalid#

PRORM_KLOCK_ROOTS is not valid. · HTTP — · retryable: no · since 4.9.2
Message: PRORM_KLOCK_ROOTS must be a JSON array of {kid, x} Ed25519 roots
What it means. The development/staging root override is not a JSON array of {kid, x} keys. It is ignored in production builds.
Fix.
1.
Fix or unset PRORM_KLOCK_ROOTS.
Raised by: device agent / klock core (src/klock/keys.ts), outh (Go) (outh/internal/klockv2/roots.go).

klock_unconfigured#

The klock service pair is not configured. · HTTP — · retryable: no · since 4.9.2
Message: KLOCK_RPC_PUB is not configured: ApiInternal refuses every call
What it means. A service key (KLOCK_RPC_PUB, API_RPC_PUB, a klock seed) is missing or malformed, so every RPC call is refused.
Fix.
1.
Operators: set the missing secret named in the message on the Worker and redeploy.
Raised by: API (api/controllers/klockGrants.ts), klock service (api/klock/env.ts).

klock_v2_unavailable#

klock v2 is not available on this API. · HTTP 503 · retryable: yes · since 4.9.2
Message: klock v2 is not available: cannot {what}
What it means. The API cannot sign or verify grants: KLOCK_GRANT_KEY is not set, no verified keyset is published, or the keyset does not certify the key. Legacy bearers and API keys keep working.
Fix.
1.
Users: sign in with the legacy flow meanwhile (prorm login --legacy), or retry later.
2.
Operators: set KLOCK_GRANT_KEY and publish a keyset (see docs/runbooks/credential-rotation.md).
Raised by: API (api/controllers/klockGrants.ts), API (api/security/controllers/klock.ts).
Related: no_keyset, klock_unconfigured.

mcp_unavailable#

MCP forwarding is unavailable. · HTTP 503 · retryable: yes · since 4.9.2
Message: The MCP tool registry on this API is out of date
What it means. The API cannot run MCP tool calls: its copy of the tool registry has no capability annotations (an older ts-prorm-orm), or the key that confirmations and forwarded calls are signed with is not configured.
Fix.
1.
Operators: install a ts-prorm-orm whose mcp/registry has needs, and set JWT_SECRET.
2.
Users: retry later. The local prorm mcp and ordinary CLI commands keep working.
Raised by: API (api/security/controllers/mcpForward.ts).

no_keyset#

No keyset is published. · HTTP 503 · retryable: yes · since 4.9.2
Message: No klock keyset is published
What it means. No API-signed keyset exists yet (the key ceremony is pending), or no roots are pinned. Nothing can verify a grant.
Fix.
1.
Retry later. Operators: publish the keyset.
Raised by: API (api/basic/routes/security.js), klock service (api/klock/routes/public.ts), klock service (api/klock/lib/trust.ts), MCP Worker (workers/mcp/src/auth.ts).
Related: klock_v2_unavailable.

secrets_key_missing#

The API cannot store secrets. · HTTP 503 · retryable: no · since 4.5.0
Message: Passwordless access needs SECRETS_KEY to be configured
What it means. The control plane cannot store secrets encrypted, so it refuses to issue sessions, roles, TOTP secrets or the sign-in relay.
Fix.
1.
Operators: configure SECRETS_KEY on the API.
Raised by: API (api/security/routes/passwordless.js), API (api/basic/routes/security.js).

tls_unavailable#

No WebCrypto here. · HTTP — · retryable: no · since 4.9.2
Message: WebCrypto is not available here
What it means. The TLS provider makes keys and CSRs with WebCrypto (Node 20+, Bun, Workers). This runtime has none.
Fix.
1.
Use Node.js 20 or newer.
Raised by: device agent / klock core (src/klock/providers/tls.ts).

Protocol and RPC#

api_unavailable#

The API did not answer the klock service. · HTTP 503 · retryable: yes · since 4.9.2
Message: the revocation feed is unavailable
What it means. The klock service could not reach the API (feed, grant minting).
Fix.
1.
Retry later; check https://status.prod-orm.io.
Raised by: klock service (api/klock/routes/public.ts), klock service (api/klock/lib/enrolment.ts).

bad_arguments#

Bad MCP tool arguments. · HTTP 400 · retryable: no · since 4.9.2
Message: Missing argument: {name}
What it means. The tool’s arguments are not an object, or a required argument is missing or empty.
Fix.
1.
Call the tool again with the arguments its inputSchema requires.
Raised by: API (api/security/controllers/mcpForward.ts).

bad_intent#

The signed MCP request is not one tool call. · HTTP 400 · retryable: no · since 4.9.2
Message: The signed body is not one JSON-RPC tools/call
What it means. A Klock-signed MCP request relayed to /internal/mcp/forward must be exactly one JSON-RPC tools/call. The body was not JSON, was a batch, or was another method.
Fix.
1.
Send one tools/call per request. A client that batches should call tools one at a time.
Raised by: API (api/security/controllers/mcpForward.ts).
Related: intent_mismatch.

bad_request#

Bad request. · HTTP 400 · retryable: no · since 4.9.2
Message: the body is not an object
What it means. The klock service, the DeviceGuard or a klock API route could not use the request body or parameters. The message says which field.
Fix.
1.
Upgrade the CLI; a hand-built request is missing a field.
Raised by: klock service (api/klock/routes/router.ts), klock service (api/klock/lib/http.ts), API (api/sockets/device-guard.ts), API (api/security/controllers/klock.ts).

body_too_large#

The body is too large. · HTTP 413 · retryable: no · since 4.9.2
Message: the body is over {limit} bytes
What it means. Request bodies to the klock service are capped.
Fix.
1.
Send less (fewer events per sync report).
Raised by: klock service (api/klock/routes/router.ts), klock service (api/klock/lib/http.ts), API (api/sockets/device-guard.ts), API (api/security/controllers/klock.ts).

intent_mismatch#

The relayed MCP call is not the one the device signed. · HTTP 400 · retryable: no · since 4.9.2
Message: The relayed tool call is not the one the device signed
What it means. The MCP Worker relayed a tool name or arguments that differ from the bytes the device signed. The API takes the call only from the signed bytes and refuses a changed relay, so a compromised Worker cannot invent or alter an action.
Fix.
1.
Retry the call. If it keeps happening, something between the client and the API is changing requests: report it.
Raised by: API (api/security/controllers/mcpForward.ts).
Related: bad_intent, signature_invalid.

internal#

klock could not complete the request. · HTTP 500 · retryable: yes · since 4.9.2
Message: klock could not complete the request
What it means. An unexpected error in the klock service.
Fix.
1.
Retry; report it with the time if it persists.
Raised by: klock service (api/klock/routes/router.ts), klock service (api/klock/lib/http.ts), API (api/sockets/device-guard.ts), API (api/security/controllers/klock.ts).

method_not_allowed#

Method not allowed. · HTTP 405 · retryable: no · since 4.9.2
Message: use {allow}
What it means. The route exists but not with this method.
Fix.
1.
Upgrade the CLI.
Raised by: klock service (api/klock/routes/router.ts), klock service (api/klock/lib/http.ts), API (api/sockets/device-guard.ts), API (api/security/controllers/klock.ts).

not_found#

Not found. · HTTP 404 · retryable: no · since 4.9.2
Message: no such route
What it means. The route or session does not exist (or is not yours; the API does not say which).
Fix.
1.
Check the id: prorm sessions, prorm devices list.
Raised by: klock service (api/klock/routes/router.ts), klock service (api/klock/lib/http.ts), API (api/sockets/device-guard.ts), API (api/security/controllers/klock.ts).

not_implemented#

Not available yet. · HTTP 501 · retryable: no · since 4.9.2
Message: pairing is not available yet (S2)
What it means. The endpoint is part of a later klock v2 batch (pairing, credentials, transfers).
Fix.
1.
Upgrade the service, or wait for the release that ships it.
Raised by: klock service (api/klock/routes/router.ts), klock service (api/klock/lib/http.ts), API (api/sockets/device-guard.ts), API (api/security/controllers/klock.ts).

policy_unavailable#

The klock service could not read the access rules. · HTTP 503 · retryable: yes · since 4.9.2
Message: the access rules could not be read
What it means. The klock service asks the API for the account, team and device access rules (and behaviour profiles) before it hands out a grant, enrols a device or issues a credential. The API did not answer, so klock fails closed: at enrolment and credential issue the request is refused with 503; at sync the device still syncs but gets grantError: "policy_unavailable" and no grant.
Fix.
1.
Retry later; the device keeps its current grant until it expires, and the next sync tries again.
2.
Check https://status.prod-orm.io.
3.
Operators: check the klock Worker’s API service binding and that the API’s KLOCK_RPC_PUB matches klock’s KLOCK_RPC_KEY.
Raised by: klock service (api/klock/lib/policy.ts), klock service (api/klock/routes/sync.ts), klock service (api/klock/routes/enrol.ts).
Related: access_denied, api_unavailable, klock_unconfigured.

rate_limited#

Rate limited. · HTTP 429 · retryable: yes · since 4.9.2
Message: too many syncs
What it means. Too many syncs, or guest grants from one address or device. Retry-After says when to try again.
Fix.
1.
Wait for Retry-After seconds, then retry.
Raised by: klock service (api/klock/routes/router.ts), klock service (api/klock/lib/http.ts), API (api/sockets/device-guard.ts), API (api/security/controllers/klock.ts).

rpc_args_mismatch#

The arguments are not the ones signed. · HTTP — · retryable: no · since 4.9.2
Message: the arguments are not the ones signed
What it means. The RPC arguments’ digest does not match the signed one. RPC errors cross the service binding as Errors whose message starts with the code (rpc_args_mismatch: …); users never see them directly, only as a failed request that depended on the call.
Fix.
1.
This is internal to the service pair. Operators: check that API_RPC_KEY/API_RPC_PUB and KLOCK_RPC_PUB are the matching pair on both Workers, and that both are deployed from the same release.
Raised by: klock service (api/klock/lib/rpc.ts), API (api/controllers/klockGrants.ts).

rpc_bad_signature#

The call signature does not verify. · HTTP — · retryable: no · since 4.9.2
Message: the call signature does not verify: {reason}
What it means. The RPC JWS does not verify against the pinned service key. RPC errors cross the service binding as Errors whose message starts with the code (rpc_bad_signature: …); users never see them directly, only as a failed request that depended on the call.
Fix.
1.
This is internal to the service pair. Operators: check that API_RPC_KEY/API_RPC_PUB and KLOCK_RPC_PUB are the matching pair on both Workers, and that both are deployed from the same release.
Raised by: klock service (api/klock/lib/rpc.ts), API (api/controllers/klockGrants.ts).

rpc_clock_skew#

The call was signed too far from now. · HTTP — · retryable: yes · since 4.9.2
Message: the call was signed too far from now
What it means. The RPC iat is outside the allowed window: the two Workers’ clocks disagree or the call was delayed. RPC errors cross the service binding as Errors whose message starts with the code (rpc_clock_skew: …); users never see them directly, only as a failed request that depended on the call.
Fix.
1.
This is internal to the service pair. Operators: check that API_RPC_KEY/API_RPC_PUB and KLOCK_RPC_PUB are the matching pair on both Workers, and that both are deployed from the same release.
Raised by: klock service (api/klock/lib/rpc.ts), API (api/controllers/klockGrants.ts).

rpc_malformed#

The call is malformed. · HTTP — · retryable: no · since 4.9.2
Message: the call has no usable nonce
What it means. The RPC signature is too long, its claims are not an object, or it has no usable nonce. RPC errors cross the service binding as Errors whose message starts with the code (rpc_malformed: …); users never see them directly, only as a failed request that depended on the call.
Fix.
1.
This is internal to the service pair. Operators: check that API_RPC_KEY/API_RPC_PUB and KLOCK_RPC_PUB are the matching pair on both Workers, and that both are deployed from the same release.
Raised by: klock service (api/klock/lib/rpc.ts), API (api/controllers/klockGrants.ts).

rpc_replay#

The call nonce has been used. · HTTP — · retryable: yes · since 4.9.2
Message: the call nonce has been used
What it means. RPC nonces are single-use. RPC errors cross the service binding as Errors whose message starts with the code (rpc_replay: …); users never see them directly, only as a failed request that depended on the call.
Fix.
1.
This is internal to the service pair. Operators: check that API_RPC_KEY/API_RPC_PUB and KLOCK_RPC_PUB are the matching pair on both Workers, and that both are deployed from the same release.
Raised by: klock service (api/klock/lib/rpc.ts), API (api/security/controllers/klock.ts).

rpc_unsigned#

The call is not signed. · HTTP — · retryable: no · since 4.9.2
Message: the call is not signed
What it means. An API ↔ klock service RPC call carried no signature. RPC errors cross the service binding as Errors whose message starts with the code (rpc_unsigned: …); users never see them directly, only as a failed request that depended on the call.
Fix.
1.
This is internal to the service pair. Operators: check that API_RPC_KEY/API_RPC_PUB and KLOCK_RPC_PUB are the matching pair on both Workers, and that both are deployed from the same release.
Raised by: klock service (api/klock/lib/rpc.ts), API (api/controllers/klockGrants.ts).

rpc_wrong_audience#

The call is for another service. · HTTP — · retryable: no · since 4.9.2
Message: the call is not for {aud}
What it means. The RPC claims name another audience. RPC errors cross the service binding as Errors whose message starts with the code (rpc_wrong_audience: …); users never see them directly, only as a failed request that depended on the call.
Fix.
1.
This is internal to the service pair. Operators: check that API_RPC_KEY/API_RPC_PUB and KLOCK_RPC_PUB are the matching pair on both Workers, and that both are deployed from the same release.
Raised by: klock service (api/klock/lib/rpc.ts), API (api/controllers/klockGrants.ts).

rpc_wrong_caller#

Signed by the wrong service. · HTTP — · retryable: no · since 4.9.2
Message: the call is not signed by {keyid}
What it means. The call is signed by a key other than the pinned caller key (klock service side only). RPC errors cross the service binding as Errors whose message starts with the code (rpc_wrong_caller: …); users never see them directly, only as a failed request that depended on the call.
Fix.
1.
This is internal to the service pair. Operators: check that API_RPC_KEY/API_RPC_PUB and KLOCK_RPC_PUB are the matching pair on both Workers, and that both are deployed from the same release.
Raised by: klock service (api/klock/lib/rpc.ts).

rpc_wrong_method#

The call is signed for another method. · HTTP — · retryable: no · since 4.9.2
Message: the signature is for another method
What it means. The signature covers a different RPC method. RPC errors cross the service binding as Errors whose message starts with the code (rpc_wrong_method: …); users never see them directly, only as a failed request that depended on the call.
Fix.
1.
This is internal to the service pair. Operators: check that API_RPC_KEY/API_RPC_PUB and KLOCK_RPC_PUB are the matching pair on both Workers, and that both are deployed from the same release.
Raised by: klock service (api/klock/lib/rpc.ts), API (api/controllers/klockGrants.ts).

transfer_chunk_exists#

That chunk is already stored. · HTTP 409 · retryable: no · since 4.9.2
Message: the chunk is already stored; a chunk cannot be replaced
What it means. A chunk of a transfer is written once. Uploading the same bytes again is accepted (a retry); different bytes at the same index are refused, so a stored chunk cannot be swapped.
Fix.
1.
Send the files again as a new transfer with prorm klock cp.
Raised by: klock service (api/klock/routes/transfers.ts).

transfer_chunk_invalid#

A chunk was refused. · HTTP 400 · retryable: no · since 4.9.2
Message: the chunk is not one this transfer has
What it means. Every sealed chunk has exactly one allowed length (4 MiB plus the 16-byte tag, the last one shorter) and index (below the chunk count the offer declared). This one had another length or index, or was not base64url. It is recorded as an event.
Fix.
1.
Send again with prorm klock cp.
Raised by: klock service (api/klock/routes/transfers.ts).
Related: transfer_chunk_exists.

transfer_chunk_missing#

A chunk is no longer on the relay. · HTTP 410 · retryable: no · since 4.9.2
Message: the chunk is no longer on the relay
What it means. The relay no longer holds a chunk of this transfer: it ended (and its chunks were deleted) while it was being downloaded, or the bucket’s 24-hour lifecycle rule removed it first.
Fix.
1.
Ask the sender to send it again with prorm klock cp.
Raised by: klock service (api/klock/lib/transfer-store.ts), klock service (api/klock/routes/transfers.ts).
Related: transfer_expired.

transfer_incomplete#

Not every chunk has been uploaded. · HTTP 409 · retryable: yes · since 4.9.2
Message: some chunks have not been uploaded
What it means. The sender asked to complete a transfer before every chunk the offer declared was stored.
Fix.
1.
Send again with prorm klock cp (an interrupted upload is not resumed).
Raised by: klock service (api/klock/routes/transfers.ts).

transfer_manifest_invalid#

The file list was refused. · HTTP 400 · retryable: no · since 4.9.2
Message: the manifest is not acceptable: {reason}
What it means. The relay applies the same rules as prorm klock accept: relative plain names (no absolute path, drive letter, .., . or empty segment, no control characters, each segment at most 255 bytes), no duplicates, sizes and SHA-256s well formed, at most 10000 files, and totalBytes, chunks and chunkSize that agree with the list.
Fix.
1.
Send the files from a directory without such names.
2.
If prorm klock cp itself sent this, report it: the client checks the same rules first.
Raised by: klock service (api/klock/routes/transfers.ts).

upgrade_required#

A WebSocket is required. · HTTP 426 · retryable: no · since 4.9.2
Message: GET /v2/channel is a WebSocket
What it means. /v2/channel is a WebSocket endpoint.
Fix.
1.
Connect with a WebSocket upgrade (prorm klock agent does).
Raised by: klock service (api/klock/routes/router.ts), klock service (api/klock/lib/http.ts), API (api/sockets/device-guard.ts), API (api/security/controllers/klock.ts).

v1 passwordless grants#

device_signature_required#

This session takes only device-signed requests. · HTTP 403 · retryable: no · since 4.9.2
Message: This session is bound to a device key: sign the request with it (klock v2)
What it means. The passwordless session was bound to a device key with protocol v2, so its v1 secret no longer opens it. Whoever still holds the old secret — an old copy of the file, outh before the upgrade — is refused.
Fix.
1.
Use the upgraded (v2) klock on the bound host.
2.
For clients that still need the secret, bind with the default v1+v2 instead of v2.
Raised by: API (api/security/routes/passwordless.js).
Related: not_bound.

v1_beyond_session#

Outside the session’s ceiling. · HTTP 403 · retryable: no · since 4.5.0
Message: The grant exceeds the session: {what}
What it means. The request is outside the session’s ceiling (or the role’s current scope).
Fix.
1.
Ask for less, or have the owner widen the role or issue a wider session.
Raised by: API (api/security/routes/passwordless.js).

v1_client_cert_required#

The session needs its client certificate. · HTTP 401 · retryable: no · since 4.5.0
Message: This session presents a client certificate; none arrived.
What it means. A --auth tls session was used without its certificate, or with someone else’s.
Fix.
1.
Use the .klock with its tls block through StoreKey, which presents it on the mutually-authenticated endpoint.
Raised by: API (api/security/routes/passwordless.js).

v1_credential_malformed#

The credential is not a v1 grant. · HTTP 403 · retryable: no · since 4.5.0
Message: A credential is <body>.<signature>
What it means. The credential is not <body>.<signature> in base64url, or its body is not a grant, names no role, or permits nothing.
Fix.
1.
Sign with the CLI, StoreKey, or a current outh.
Raised by: API (api/security/controllers/passwordless.ts), device agent / klock core (src/klock/v1.ts), outh (Go) (outh/internal/grant/grant.go).

v1_grant_not_canonical#

The grant is not canonical. · HTTP 403 · retryable: no · since 4.5.0
Message: The body carries more than the grant it decodes to
What it means. The signed body is not canonical: hand-built, or signed by an older outh that HTML-escaped <, > and & in table names.
Fix.
1.
Sign with the CLI, StoreKey, or a current outh.
Raised by: API (api/security/controllers/passwordless.ts), device agent / klock core (src/klock/v1.ts), outh (Go) (outh/internal/grant/grant.go).

v1_kerberos_refused#

The session needs its Kerberos ticket. · HTTP 401 · retryable: no · since 4.5.0
Message: This session presents a Kerberos ticket; send it as Authorization: Negotiate <token>.
What it means. A --auth kerberos session was used without its ticket, with someone else’s, or the file has no kerberos block.
Fix.
1.
Use the .klock with its kerberos block through StoreKey.
2.
For outh spnego, issue with --auth kerberos.
Raised by: API (api/security/routes/passwordless.js), library (src/store-key.ts).

v1_kerberos_unavailable#

The Kerberos authority is unavailable. · HTTP 503 · retryable: yes · since 4.5.0
Message: The Kerberos authority could not check the ticket: {reason}
What it means. The API could not reach the Kerberos authority, or it is not configured.
Fix.
1.
Retry later. Operators: configure KERBEROS_AUTHORITY_TOKEN.
Raised by: API (api/security/routes/passwordless.js).

v1_query_invalid#

Not a passwordless query. · HTTP 400 · retryable: no · since 4.5.0
Message: A query is one of select, insert, update or delete
What it means. A passwordless query is an intent (select\|insert\|update\|delete) naming its table, not SQL.
Fix.
1.
Send { op, table, … }; see prorm passwordless query --help.
Raised by: API (api/security/routes/passwordless.js), CLI (src/cli/basic/commands/passwordless.ts).

v1_role_gone#

The granted role no longer exists. · HTTP 403 · retryable: no · since 4.5.0
Message: The role this session was granted no longer exists
What it means. The role behind a roles grant session was deleted.
Fix.
1.
Grant a current role: prorm roles grant.
Raised by: API (api/security/routes/passwordless.js).

v1_role_mismatch#

The grant is for a different role. · HTTP 403 · retryable: no · since 4.5.0
Message: The grant is for a different role than the session
What it means. The role or entId in the file was changed, or overridden with --role / --ent-id.
Fix.
1.
Remove the override, or restore the file.
Raised by: API (api/security/routes/passwordless.js).

v1_session_unusable#

That session cannot be used. · HTTP 403 · retryable: no · since 4.5.0
Message: That session cannot be used
What it means. The session is unknown, revoked, or past its expiresAt. The API deliberately does not say which.
Fix.
1.
Re-issue: prorm passwordless issue --database <id> --read.
Raised by: API (api/security/routes/passwordless.js).

v1_signature_mismatch#

The signature does not match this session. · HTTP 403 · retryable: no · since 4.5.0
Message: The signature does not match this session
What it means. The secret in the file is not this session’s: the file was re-issued, or belongs to another session.
Fix.
1.
Use the .klock that belongs to that sessionId, or re-issue.
Raised by: API (api/security/controllers/passwordless.ts), device agent / klock core (src/klock/v1.ts), outh (Go) (outh/internal/grant/grant.go).

v1_unknown#

Unknown session or database. · HTTP 404 · retryable: no · since 4.5.0
Message: Unknown session
What it means. The session or database id does not exist (or is not yours).
Fix.
1.
Check prorm passwordless list and the database id.
Raised by: API (api/security/routes/passwordless.js).

v1_window_expired#

The grant’s window has passed. · HTTP 403 · retryable: yes · since 4.5.0
Message: The grant expired about {age} seconds ago
What it means. The grant’s window is more than one window behind the server’s clock, usually because the client clock is slow.
Fix.
1.
Sync the clock (NTP). Grants are signed per request, so retrying with a correct clock works.
Raised by: API (api/security/controllers/passwordless.ts), device agent / klock core (src/klock/v1.ts), outh (Go) (outh/internal/grant/grant.go).

v1_window_not_started#

The grant’s window has not started. · HTTP 403 · retryable: yes · since 4.5.0
Message: The grant is for a window that has not started
What it means. The client clock is ahead of the server’s.
Fix.
1.
Sync the clock.
Raised by: API (api/security/controllers/passwordless.ts), device agent / klock core (src/klock/v1.ts), outh (Go) (outh/internal/grant/grant.go).

v1_wrong_database#

That session is for a different database. · HTTP 403 · retryable: no · since 4.5.0
Message: That session is for a different database
What it means. The :id in the path is not the session’s database. A .klock written before databaseId was recorded sends the uuid when the holder is not signed in, which an API without the uuid/id fix refuses.
Fix.
1.
Re-issue the file (it then records databaseId).
2.
Or pass the numeric id: --database <id> or $OUTH_DATABASE; for StoreKey, databaseId.
Raised by: API (api/security/routes/passwordless.js).
Modified at 2026-10-04 00:40:16
Previous
InfluxDB: structured Flux pipelines
Next
klock — the `.klock` file
Built with