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
- Set PAPERCLIP_CLOUD_RUNTIME_IDENTITY_JWKS in the server environment to the JWKS JSON published by the Cloud control plane
- Restart the server after adding the env var so the new environment is picked up
- Verify the variable name spelling in your deployment config (docker-compose, k8s secret, .env)
- 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
- Provision PAPERCLIP_CLOUD_RUNTIME_IDENTITY_JWKS as part of deployment templates/secrets from day one
- Add a startup config check that fails fast with a clear message when the var is missing
- Keep the env var name in one constants module to avoid typos across manifests
- Document the requirement in deployment docs for off-Cloud vs Cloud installs
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
- Codex working directory inside the host HOME requires an ass
- managed_profile_not_found
- PAPERCLIP_EVAL_MAX_CAMPAIGN_COST_USD must be a positive fini
- A trusted viewer build is required for public chat reports
- Private state directory is not a real directory: ${diagnosti
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/bc1eb366c55a9a03.
Report an issue: GitHub.