paperclipai/paperclip · critical
Persisted Cloud runtime identity contains an invalid origin
Error message
Persisted Cloud runtime identity contains an invalid origin
What it means
After confirming the stack id matches, assertPersistedIdentityMatchesStack validates that both previousOrigin and canonicalOrigin stored in the durable Cloud runtime identity row are exact HTTPS origins: absolute https URLs, no credentials, no path/query/hash, exactly equal to their parsed origin, and at most 2048 chars. If either stored origin fails exactHttpsOrigin, startup throws this error. It prevents a corrupted or tampered persisted identity from driving later URL/env derivation.
Source
Thrown at server/src/services/cloud-runtime-identity.ts:163
const parsed = JSON.parse(env.PAPERCLIP_RUNTIME_API_CANDIDATES_JSON ?? "[]");
return Array.isArray(parsed) ? parsed.filter((value): value is string => typeof value === "string") : [];
} catch {
return [];
}
})();
env.PAPERCLIP_RUNTIME_API_CANDIDATES_JSON = JSON.stringify([
identity.canonicalOrigin,
...existingCandidates.filter((candidate) => candidate !== identity.canonicalOrigin),
]);
}
function assertPersistedIdentityMatchesStack(row: PersistedRuntimeIdentity, env: NodeJS.ProcessEnv) {
const configuredStackId = nonEmpty(env.PAPERCLIP_CLOUD_STACK_ID);
if (!configuredStackId || configuredStackId !== row.stackId) {
throw new Error("Persisted Cloud runtime identity does not match PAPERCLIP_CLOUD_STACK_ID");
}
if (!exactHttpsOrigin(row.previousOrigin) || !exactHttpsOrigin(row.canonicalOrigin)) {
throw new Error("Persisted Cloud runtime identity contains an invalid origin");
}
if (!STACK_SLUG_PATTERN.test(row.stackSlug) || new URL(row.canonicalOrigin).hostname.split(".")[0] !== row.stackSlug) {
throw new Error("Persisted Cloud runtime identity contains an invalid stack slug");
}
}
/** Load the durable claim before auth, routes, and child-runtime configuration. */
export async function initializeCloudRuntimeIdentity(
db: Db,
env: NodeJS.ProcessEnv = process.env,
): Promise<CloudRuntimeIdentitySnapshot | null> {
startupOrigin = configuredStartupOrigin(env);
// Self-hosted servers have no Cloud stack identity to restore. Avoid touching
// the singleton table on that path; besides keeping the feature inert, this
// preserves lightweight startup/test database seams that intentionally do
// not construct a database client.
if (!nonEmpty(env.PAPERCLIP_CLOUD_STACK_ID)) {
initialized = true;View on GitHub (pinned to 01ad858492)
Solutions
- Inspect the instanceSettings row with singletonKey 'cloud-runtime-identity/v1' and correct previousOrigin/canonicalOrigin to exact bare https origins (e.g. 'https://stack.example.com' — no trailing slash, path, query, or credentials).
- If the row is unrecoverable or was written by a failed/aborted claim, remove the row and re-run the one-time identity assertion (applyCloudRuntimeIdentityAssertion) to re-claim cleanly.
- Verify no migration or import step lowercased/normalized the URL with a trailing slash or rewrote https to http.
Example fix
// persisted row in instance_settings.general // before canonicalOrigin: "https://my-stack.example.com/" // after "canonicalOrigin": "https://my-stack.example.com"
Defensive patterns
Strategy: validation
Validate before calling
function isExactHttpsOrigin(value: unknown): boolean {
if (typeof value !== "string" || !value || value.length > 2048) return false;
try {
const u = new URL(value);
return u.protocol === "https:" && !u.username && !u.password &&
u.pathname === "/" && !u.search && !u.hash && u.origin === value;
} catch { return false; }
}
// assert before writing/claiming:
if (!isExactHttpsOrigin(previousOrigin) || !isExactHttpsOrigin(canonicalOrigin)) {
throw new Error("origins must be exact bare https origins, e.g. https://stack.example.com");
} Type guard
function isExactHttpsOrigin(value: unknown): value is string {
if (typeof value !== "string" || !value || value.length > 2048) return false;
try {
const u = new URL(value);
return u.protocol === "https:" && !u.username && !u.password &&
u.pathname === "/" && !u.search && !u.hash && u.origin === value;
} catch { return false; }
} Prevention
- Store origins with no trailing slash, path, query, credentials, or port ambiguity
- Only write identity rows through applyCloudRuntimeIdentityAssertion, never hand-edit instance_settings
- Validate origins with the same exactHttpsOrigin rules in any custom migration tooling
- Use https:// URLs from the Cloud control plane verbatim
When it happens
Trigger: initializeCloudRuntimeIdentity loads a persisted identity row whose previousOrigin or canonicalOrigin fails exactHttpsOrigin: not parseable as a URL, not https scheme, contains username/password, has a path other than '/', has query string or hash, includes a trailing slash or port mismatch so value !== parsed.origin, is empty, or exceeds 2048 characters.
Common situations: The instance_settings row was hand-edited or migrated incorrectly (e.g. stored 'https://example.com/' with trailing slash, or an http:// origin); a partial write or data import corrupted the JSON; an operator set a non-HTTPS internal URL during a manual claim; restoring a DB dump from an environment with differently shaped origins.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- Persisted Cloud runtime identity does not match PAPERCLIP_CL
- Persisted Cloud runtime identity contains an invalid stack s
- Cloud runtime identity previous or canonical origin is inval
- devUiUrl must use http or https protocol
- ${label} has existing tables but no migration journal. Run m
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/91c4e89386c2a123.
Report an issue: GitHub.