paperclipai/paperclip · error
OpenCode request ${input.requestId} is no longer pending
Error message
OpenCode request ${input.requestId} is no longer pending What it means
Runtime requests (permission approvals, native questions) are tracked in `#pendingRuntimeRequests`. `resolveRuntimeRequest` throws when the given `requestId` is no longer in that map — it was already resolved, rejected, handed off, expired, or dropped when the session closed. This prevents double-submission of an answer to OpenCode's permission/question reply APIs.
Source
Thrown at packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.ts:626
`/session/${encodeURIComponent(this.#providerSessionId)}/abort`,
{ method: "POST" },
);
}
pendingRuntimeRequests(): HarnessRuntimeRequest[] {
return [...this.#pendingRuntimeRequests.values()].map(({ request }) =>
structuredClone(request),
);
}
async resolveRuntimeRequest(input: {
requestId: string;
turnId: string;
resolution: HarnessRuntimeRequestResolution;
}): Promise<void> {
const pending = this.#pendingRuntimeRequests.get(input.requestId);
if (!pending)
throw new Error(
`OpenCode request ${input.requestId} is no longer pending`,
);
if (
pending.request.turnId !== input.turnId ||
this.#activeTurnId !== input.turnId
) {
throw new Error(
`OpenCode request ${input.requestId} belongs to a stale turn`,
);
}
const resolution = parseHarnessRuntimeRequestResolution(
pending.request.requestKind,
input.resolution,
pending.request.input,
);
if (pending.settling)
throw new Error(
`OpenCode request ${input.requestId} is already settling`,View on GitHub (pinned to 01ad858492)
Solutions
- List currently answerable requests with `session.pendingRuntimeRequests()` and only call `resolveRuntimeRequest` for ids present there.
- Treat the error as idempotent success: if the request was already resolved, the intended effect likely happened — log and continue.
- Do not persist requestId resolution across process restarts without replaying `pendingRuntimeRequests()`; recover state before resolving.
- Debounce/deduplicate resolution calls (e.g. disable the button once resolution starts) to avoid double submission.
Example fix
// before
await session.resolveRuntimeRequest({ requestId, turnId, resolution }); // throws if gone
// after
const pending = session.pendingRuntimeRequests().find(r => r.requestId === requestId);
if (pending) {
await session.resolveRuntimeRequest({ requestId, turnId, resolution });
} Defensive patterns
Strategy: validation
Validate before calling
const exists = session.pendingRuntimeRequests().some(r => r.requestId === requestId); if (!exists) return; // already resolved or expired
Type guard
function isPending(session, requestId) { return session.pendingRuntimeRequests().some(r => r.requestId === requestId); } Try / catch
try {
await session.resolveRuntimeRequest({ requestId, turnId, resolution });
} catch (e) {
if (e.message.includes('is no longer pending')) {
logger.info({ requestId }, 'runtime request already resolved; treating as no-op');
} else throw e;
} Prevention
- Check `pendingRuntimeRequests()` before resolving.
- Deduplicate resolution calls (single-flight per requestId).
- Treat this error as idempotent success in reconcilers.
- Recover pending state after restarts before replaying resolutions.
When it happens
Trigger: Calling `resolveRuntimeRequest({ requestId, turnId, resolution })` for a request that was already resolved earlier in this run, auto-expired via `handoffRuntimeRequest`, cancelled by `close()`, or that never existed on this session (e.g. after a restart the in-memory map is empty).
Common situations: A UI queues a permission answer and a durable handoff resolves the request first, then the queued answer is submitted; a process restart loses the pending map while the caller retries; the user double-clicks Approve and both clicks hit `resolveRuntimeRequest`.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- OpenCode request ${input.requestId} is already settling
- OpenCode request ${input.requestId} belongs to a stale turn
- A different semantic result was already committed
- OpenCode evals require exact version 1.18.17; received ${ver
- Invalid ${name} JSON: ${err instanceof Error ? err.message :
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/f3ee018770b94a9b.
Report an issue: GitHub.