paperclipai/paperclip · error · Error
Discord command registration persistence unproven
Error message
Discord command registration persistence unproven
What it means
The internal persist() step calls the caller-supplied commit(state, next) hook to durably store the new registration state; any throw is converted to 'Discord command registration persistence unproven'. Because the next in-memory state is only adopted after commit succeeds, a failure means the new phase could not be proven durable and reconciliation aborts.
Source
Thrown at server/src/services/chat-discord-command-registration.ts:449
...input,
scope: state.scope,
state,
runtimeFence: Object.freeze(runtimeFence.data),
verifiedIdentity: Object.freeze({ ...input.verifiedIdentity }),
};
const authorize = async (stage: DiscordCommandRegistrationStage) => {
try {
await input.authorize(stage);
} catch {
throw new Error("Discord command registration authorization denied");
}
};
const persist = async (next: DiscordCommandRegistration) => {
freezeState(next);
try {
await input.commit(state!, next);
} catch {
throw new Error("Discord command registration persistence unproven");
}
state = next;
};
const settle = async (
command: RemoteCommand,
): Promise<DiscordCommandRegistrationResult> => {
const next: Extract<DiscordCommandRegistration, { phase: "registered" }> = {
schema: state!.schema,
scope: state!.scope,
ownerId: state!.ownerId,
phase: "registered",
receipt: {
commandId: command.id,
version: command.version,
definitionDigest: definitionDigest(state!.ownerId),
},
};
freezeState(next);View on GitHub (pinned to 01ad858492)
Solutions
- Check the commit hook's own storage layer for the underlying error (it is swallowed here).
- Retry reconciliation once the database is healthy; state is unchanged on failure so it is safe.
- Fix constraint/schema mismatches between the state blob and the persistence table.
- Make the commit hook idempotent and retryable for transient DB errors.
Example fix
// before (app's commit hook)
await db.insert(registrations).values(next); // throws on conflict
// after
await db.insert(registrations)
.values(next)
.onConflictDoUpdate({ target: registrations.key, set: next }); Defensive patterns
Strategy: retry
Try / catch
try { await reconcileDiscordCommandRegistration(input); }
catch (e) {
if ((e as Error).message === "Discord command registration persistence unproven") {
await sleep(backoff()); return retry(); // in-memory state unchanged; safe to retry
}
throw e;
} Prevention
- Make commit hooks idempotent and conflict-tolerant (upsert semantics).
- Monitor DB health/pool saturation; persist failures are usually infra-level.
- Keep the persisted state schema in sync with what freeze/commit expects.
When it happens
Trigger: The commit callback throws — database unavailable, unique-constraint conflict, transaction deadlock, serialization failure, or the hook rejecting the frozen next state blob.
Common situations: Postgres connection pool exhaustion or failover during reconciliation; a migration/unique index conflict on the state row; the storage layer enforcing a schema the new state doesn't match; network blip between server and DB.
Related errors
- ${label} had drifted migration history; repaired migration j
- ${label} has existing tables but no migration journal. Run m
- Database mode is postgres but no connection string was set;
- Migration journal is not a prefix of this Paperclip checkout
- Migration journal is not current (${migrationState.pendingMi
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/a8b7ad08cc9c024e.
Report an issue: GitHub.