paperclipai/paperclip · error
Durable PRP run attachment template is invalid.
Error message
Durable PRP run attachment template is invalid.
What it means
persistRunAttachTemplate() requires its argument to be an object with a truthy `provider` field (checked via isRecord(runAttachTemplate.provider)). The template is the provider preparation payload reused for run.attach after restart, so a template without a valid provider record cannot be persisted and the call fails immediately.
Source
Thrown at packages/paperclip-runner/src/control-plane/durable-prp-control-plane.ts:1713
runAttachTemplate:
runAttachTemplate === undefined
? null
: structuredClone(runAttachTemplate),
});
this.#identity = structuredClone(identity);
this.#store.save();
}
/**
* Retain the connection-free provider preparation payload before the first
* runner bootstrap. Completed command history is bounded and may be
* compacted before a warm continuation arrives, so it cannot be the sole
* source for a later run.attach. Repeating the same write is idempotent;
* changing an established seed fails closed.
*/
persistRunAttachTemplate(runAttachTemplate: Record<string, unknown>): void {
if (!isRecord(runAttachTemplate.provider)) {
throw new Error("Durable PRP run attachment template is invalid.");
}
const existing = this.#store.state.runAttachTemplate;
if (
existing !== undefined &&
existing !== null &&
canonicalJson(existing) !== canonicalJson(runAttachTemplate)
) {
throw new Error("Durable PRP run attachment template conflicts.");
}
if (existing !== undefined && existing !== null) return;
this.#store.state.runAttachTemplate = structuredClone(runAttachTemplate);
this.#store.save();
}
issueBootstrapTicket(ttlMs = 5_000): string {
this.#store.assertWritable();
if (this.#store.state.warmTransition) {
throw new Error(View on GitHub (pinned to 01ad858492)
Solutions
- Ensure the template includes a valid provider object, e.g. { provider: { ... }, ... }, before calling persistRunAttachTemplate.
- Validate the template shape at construction time (check typeof template.provider === "object" && template.provider !== null).
- Trace where the template is built; fix the config/source that omitted the provider section.
- If the template legitimately has no provider, this API is the wrong entry point — review the intended flow.
Example fix
// before
controlPlane.persistRunAttachTemplate({ model: "opus" }); // no provider
// after
controlPlane.persistRunAttachTemplate({ provider: { name: "anthropic" }, model: "opus" }); Defensive patterns
Strategy: validation
Validate before calling
function isValidAttachTemplate(t: unknown): t is Record<string, unknown> & { provider: Record<string, unknown> } {
return typeof t === "object" && t !== null && typeof (t as any).provider === "object" && (t as any).provider !== null;
}
if (!isValidAttachTemplate(template)) throw new Error("attach template requires a provider object"); Type guard
function hasProvider(t: unknown): t is { provider: Record<string, unknown> } {
return typeof t === "object" && t !== null && "provider" in t && typeof (t as { provider: unknown }).provider === "object" && (t as { provider: unknown }).provider !== null;
} Try / catch
try {
controlPlane.persistRunAttachTemplate(template);
} catch (err) {
if (err instanceof Error && err.message.includes("run attachment template is invalid")) {
throw new Error(`attach template missing provider: ${JSON.stringify(template)}`);
} else throw err;
} Prevention
- Validate template shape (provider object present) at the point the template is built.
- Guard config loading so a missing provider section fails at startup, not at persist time.
- Type the template as { provider: ... } & Record<string, unknown> in caller code so TS catches omissions.
When it happens
Trigger: Calling persistRunAttachTemplate() with null/undefined coerced in, an object missing the provider key, provider set to a non-object (string, number, boolean), or provider explicitly null.
Common situations: Config loading produced a partial template (provider section absent); a caller passes the wrong variable; JSON round-trip dropped or renamed the provider field; template built dynamically with an optional provider that was skipped.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Worktree seed manifest is missing source path diagnostics.
- unsupported request schema
- Public attempt must contain the read-only public chat projec
- Unknown public chat payload field
- Unknown public chat projection field
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/6eb5383bd17dfd43.
Report an issue: GitHub.