paperclipai/paperclip · error · DeliveryClaimUnavailableError
question_response_delivery_claim_unavailable
Error message
question_response_delivery_claim_unavailable
What it means
DeliveryClaimUnavailableError from withClaimLease: the claim ownership check against the database failed (an exception occurred while verifying rows.length === 1). The delivery's claim lease could not be confirmed, so the operation aborts to avoid two workers processing the same delivery. It is deliberately thrown instead of proceeding on uncertain ownership.
Solutions
- Retry the delivery operation after a short backoff — the error signals an uncertain claim, not a permanent failure
- Verify database connectivity and check server logs for the correlated 'question response claim ownership check failed' warning
- Check for lock contention or long transactions holding the delivery row
- If persistent, inspect DB health (max_connections, statement_timeout) and the claim lease query
Example fix
// before
await withClaimLease(deliveryId, doDeliver); // throws on transient DB hiccup
// after
await retry(
{ retries: 3, factor: 2 },
() => withClaimLease(deliveryId, doDeliver),
{ shouldRetry: (e) => e instanceof DeliveryClaimUnavailableError },
); Defensive patterns
Strategy: retry
Validate before calling
// Pre-check DB reachability before delivery batch const ok = await db.execute(sql`SELECT 1`).then(() => true, () => false); if (!ok) await waitForDbHealth();
Type guard
function isDeliveryClaimUnavailable(e) {
return e instanceof Error && (e.name === "DeliveryClaimUnavailableError" || e.message === "question_response_delivery_claim_unavailable");
} Try / catch
try {
await withClaimLease(deliveryId, operation);
} catch (e) {
if (isDeliveryClaimUnavailable(e)) {
// uncertain ownership (db check failed): safe to retry with backoff
await backoff(retryCount++);
return retryDelivery(deliveryId);
}
throw e;
} Prevention
- Keep DB connections healthy (pool limits, statement_timeout tuned) so the ownership check does not fail spuriously
- Wrap claim-dependent work in bounded retries with exponential backoff
- Alert on repeated 'question response claim ownership check failed' warnings
- Avoid running delivery inside long transactions that hold locks on the delivery row
When it happens
Trigger: Inside withClaimLease, the ownership SELECT/UPDATE throws (DB connection failure, timeout, serialization error) so ownsClaim cannot be determined; the catch block logs 'question response claim ownership check failed' and rethrows as DeliveryClaimUnavailableError.
Common situations: Transient Postgres connectivity loss during delivery; statement timeout on the claim check; DB failover mid-delivery; heavy lock contention on the delivery row.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- native_runtime_run_missing
- ACPX provider ownership admission is closed
- ACPX runtime host already has an active turn
- Bridge envelope changed while reading.
- Bridge host response body capacity is busy.
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/90a65363213ce289.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/question-response-delivery.ts:693
.from(issueQuestionResponseDeliveries)
.where(
and(
eq(issueQuestionResponseDeliveries.id, delivery.id),
eq(issueQuestionResponseDeliveries.status, "delivering"),
eq(
issueQuestionResponseDeliveries.attemptCount,
delivery.attemptCount,
),
),
)
.limit(1)
.then((rows) => rows.length === 1);
} catch (error) {
logger.warn(
{ err: error, deliveryId: delivery.id },
"question response claim ownership check failed",
);
throw new DeliveryClaimUnavailableError();
}
if (!ownsClaim) throw new DeliveryClaimUnavailableError();
if (operationError !== undefined) throw operationError;
return result as T;
}
async function findDurableWakeRequest(input: {
companyId: string;
idempotencyKey: string;
}) {
const request = await db
.select({
agentId: agentWakeupRequests.agentId,
id: agentWakeupRequests.id,
runId: agentWakeupRequests.runId,
status: agentWakeupRequests.status,
})
.from(agentWakeupRequests)View on GitHub (pinned to 3f1d897a7c)