paperclipai/paperclip · error

PAPERCLIP_CLOUD_RUNTIME_IDENTITY_JWKS is not configured

Error message

PAPERCLIP_CLOUD_RUNTIME_IDENTITY_JWKS is not configured

What it means

Thrown by publicKeyForKid when the PAPERCLIP_CLOUD_RUNTIME_IDENTITY_JWKS environment variable is unset or empty while verifying a cloud runtime identity assertion. The verifier needs the trusted JWKS containing the Ed25519 public key referenced by the assertion's kid; without it no assertion can be verified.

Source

Thrown at server/src/services/cloud-runtime-identity.ts:236

}

function decodeJsonPart(part: string, label: string): Record<string, unknown> {
  if (!/^[A-Za-z0-9_-]+$/.test(part)) throw new Error(`Cloud runtime identity has an invalid ${label}`);
  let parsed: unknown;
  try {
    parsed = JSON.parse(Buffer.from(part, "base64url").toString("utf8"));
  } catch {
    throw new Error(`Cloud runtime identity has an invalid ${label}`);
  }
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
    throw new Error(`Cloud runtime identity has an invalid ${label}`);
  }
  return parsed as Record<string, unknown>;
}

function publicKeyForKid(env: NodeJS.ProcessEnv, kid: string) {
  const raw = nonEmpty(env.PAPERCLIP_CLOUD_RUNTIME_IDENTITY_JWKS);
  if (!raw) throw new Error("PAPERCLIP_CLOUD_RUNTIME_IDENTITY_JWKS is not configured");
  let parsed: unknown;
  try {
    parsed = JSON.parse(raw);
  } catch {
    throw new Error("PAPERCLIP_CLOUD_RUNTIME_IDENTITY_JWKS is invalid");
  }
  const keys = parsed && typeof parsed === "object" && !Array.isArray(parsed)
    ? (parsed as { keys?: unknown }).keys
    : undefined;
  if (!Array.isArray(keys)) throw new Error("PAPERCLIP_CLOUD_RUNTIME_IDENTITY_JWKS is invalid");
  const matches = keys.filter((candidate): candidate is JsonWebKey & { kid: string } => {
    if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) return false;
    const key = candidate as JsonWebKey & { kid?: unknown };
    return key.kid === kid;
  });
  if (matches.length !== 1) throw new Error("Cloud runtime identity uses an unknown signing key");
  const jwk = matches[0];
  if (jwk.kty !== "OKP" || jwk.crv !== "Ed25519" || jwk.use !== "sig" || jwk.alg !== "EdDSA" || !jwk.x || jwk.d) {

View on GitHub (pinned to 01ad858492)

Solutions

  1. Set PAPERCLIP_CLOUD_RUNTIME_IDENTITY_JWKS in the server environment to the JWKS JSON published by the Cloud control plane
  2. Restart the server after adding the env var so the new environment is picked up
  3. Verify the variable name spelling in your deployment config (docker-compose, k8s secret, .env)
  4. If running off-Cloud intentionally, disable the cloud identity claim path instead of providing an empty value

Example fix

// before
// (env missing)
// after (k8s)
env:
  - name: PAPERCLIP_CLOUD_RUNTIME_IDENTITY_JWKS
    valueFrom:
      secretKeyRef: { name: paperclip-cloud, key: runtime-identity-jwks }
Defensive patterns

Strategy: validation

Validate before calling

if (!process.env.PAPERCLIP_CLOUD_RUNTIME_IDENTITY_JWKS) {
  throw new Error("PAPERCLIP_CLOUD_RUNTIME_IDENTITY_JWKS must be set before verifying cloud identity assertions");
}

Type guard

function hasJwks(env: NodeJS.ProcessEnv): env is NodeJS.ProcessEnv & { PAPERCLIP_CLOUD_RUNTIME_IDENTITY_JWKS: string } {
  return typeof env.PAPERCLIP_CLOUD_RUNTIME_IDENTITY_JWKS === "string" && env.PAPERCLIP_CLOUD_RUNTIME_IDENTITY_JWKS.length > 0;
}

Try / catch

try {
  verifyCloudRuntimeIdentityAssertion({ compactJws: assertion, expectedPreviousOrigin: prev });
} catch (e) {
  if (String((e as Error).message).includes("is not configured")) {
    logger.error("JWKS env var missing; cannot verify cloud runtime identity", { error: e });
    // fail startup or fall back to non-cloud identity path
  } else throw e;
}

Prevention

When it happens

Trigger: verifyCloudRuntimeIdentityAssertion is called (e.g. during instance identity claim at startup or an auth flow), the JWS header parses fine, but process.env has no non-empty PAPERCLIP_CLOUD_RUNTIME_IDENTITY_JWKS value.

Common situations: Self-hosted/off-Cloud deployment where the JWKS env var was never provisioned; the env var was dropped in a Docker/Kubernetes config update or .env file not loaded; typo in the variable name in the deployment manifest.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/bc1eb366c55a9a03. Report an issue: GitHub.