paperclipai/paperclip · error · Error
paperclip_runner_file_handoff_workspace_unavailable
paperclip_runner_file_handoff_workspace_unavailable
Error message
paperclip_runner_file_handoff_workspace_unavailable
What it means
Thrown at the start of #registerDeliverable when the run's binding has no workspaceRoot (or it is empty after trim). Registering a deliverable requires a file handoff workspace to persist the artifact, so without a bound workspace the tool refuses immediately with this sentinel error code.
Solutions
- Ensure the run is created with a bound workspace so binding.workspaceRoot is populated before calling register_deliverable.
- If the run intentionally has no workspace, use a different reporting path (e.g. report_progress with the artifact content) instead of file handoff.
- Inspect the native runtime binding construction to confirm workspaceRoot is passed and not cleared by trim/normalization.
Defensive patterns
Strategy: validation
Validate before calling
if (!binding.workspaceRoot?.trim()) {
throw new Error('register_deliverable requires a workspace-bound run');
} Type guard
function hasWorkspace(b: { workspaceRoot?: string | null }): b is { workspaceRoot: string } {
return typeof b.workspaceRoot === 'string' && b.workspaceRoot.trim().length > 0;
} Prevention
- Create runs with a bound workspace when file handoff is planned
- Check binding.workspaceRoot at run startup and disable file tools if absent
- Do not clean up workspace directories before deliverables are registered
When it happens
Trigger: Calling the register_deliverable runner tool from a run whose binding.workspaceRoot is undefined/empty — e.g. API-driven or remote runs created without a workspace, or adapters that do not clone a repo workspace.
Common situations: Runs launched in headless/no-checkout mode, misconfigured native runtime that omits workspaceRoot in the binding, environments where the workspace was cleaned up before the run reported its deliverable.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- railway_workspace_required
- A trusted viewer build is required for public chat reports
- ACPX provider package manifest must be an explicit…
- ACPX provider package root must be an explicit normalized…
- ACPX runtime executable must be a bounded executable file
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/6bb0a1b4edeb27af.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/native-runtime/paperclip-runner-tool-authority.ts:923
blockedByIssueIds,
actorAgentId: this.binding.agentId,
}, tx);
if (!updated) throw new Error("paperclip_runner_task_not_found");
return {
commandId: `set-dependencies:${updated.id}:${updated.statusVersion}`,
disposition: "applied",
stateRevision: updated.statusVersion,
entityRefs: [updated.id, ...blockedByIssueIds],
scheduledWakeIds: [],
};
});
}
async #registerDeliverable(input: Record<string, unknown>): Promise<unknown> {
const idempotencyKey = requiredString(input.idempotencyKey);
const workspaceRoot = this.binding.workspaceRoot?.trim();
if (!workspaceRoot) {
throw new Error("paperclip_runner_file_handoff_workspace_unavailable");
}
let publication:
Awaited<ReturnType<typeof persistActivity>>["publication"] | null = null;
let rollbackDefinitePreCommitFailure: (() => Promise<void>) | null = null;
const result = await this.#withMutationReceipt(
"register_deliverable",
idempotencyKey,
input,
async (tx, context) => {
const prepared = await prepareNativeRunnerFileHandoff({
db: tx,
binding: {
companyId: this.binding.companyId,
issueId: this.binding.issueId,
runId: this.binding.runId,
agentId: this.binding.agentId,
workspaceRoot,
executionTargetKind: this.binding.executionTargetKind ?? "local",View on GitHub (pinned to 3f1d897a7c)