{"record":{"id":"e03de6d229791392","repo":"paperclipai/paperclip","slug":"completion-cites-a-workspace-only-file-that-the-user-cannot","errorCode":null,"errorMessage":"Completion cites a workspace-only file that the user cannot download. Before finishing, use register_deliverable for requested file outputs and cite deliverable:<attachmentId> from the receipt, with /api/attachments/<attachmentId>/content as the download link. For repository changes, cite an accessible PR or registered work product instead. No human completion approval was created.","messagePattern":"Completion cites a workspace-only file that the user cannot download\\. Before finishing, use register_deliverable for requested file outputs and cite deliverable:<attachmentId> from the receipt, with /api/attachments/<attachmentId>/content as the download link\\. For repository changes, cite an accessible PR or registered work product instead\\. No human completion approval was created\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/src/services/native-runtime/native-deliverable-feedback.ts","lineNumber":134,"sourceCode":"        throw new Error(\"Completion cites no registered attachment on this task. Use register_deliverable for the requested file and cite deliverable:<attachmentId> from its receipt. No human completion approval was created.\");\n      }\n      // A prior output (or user input) can be useful context, but does not prove\n      // this run published the newly requested output. The receipt survives a\n      // controller restart of this run; a replacement can re-register preserved\n      // workspace bytes internally rather than asking the user to confirm them.\n      if (fileRequested && attachment.originatingRunId !== binding.runId) continue;\n      if (fileRequested && !await hasCurrentPublicationReceipt(db, binding.companyId, binding.semanticToolReceipts, attachment)) {\n        throw new Error(\"This attachment has no matching verified publication receipt for this run's requested output. Inspect any preserved file and use register_deliverable to verify its current filename, size, and SHA-256, then cite the new receipt. No human completion approval was created.\");\n      }\n      registeredAttachment = true;\n      continue;\n    }\n    // URLs and typed durable refs are not workspace paths. Verification commands\n    // belong in verification; do not scan prose or upload files named by a model.\n    const localFile = /^(?:file:|\\.{0,2}\\/|[a-z]:[\\\\/])/iu.test(ref)\n      || (!/^[a-z][a-z0-9+.-]*:/iu.test(ref) && /^[^\\r\\n]+\\.[a-z0-9]{1,16}(?::\\d+(?::\\d+)?)?$/iu.test(ref));\n    if (localFile && (fileRequested || artifactRefs.has(value))) {\n      throw new Error(\"Completion cites a workspace-only file that the user cannot download. Before finishing, use register_deliverable for requested file outputs and cite deliverable:<attachmentId> from the receipt, with /api/attachments/<attachmentId>/content as the download link. For repository changes, cite an accessible PR or registered work product instead. No human completion approval was created.\");\n    }\n  }\n  if (fileRequested && !registeredAttachment) {\n    const products = refs.size ? await db.select().from(issueWorkProducts).where(and(\n      eq(issueWorkProducts.companyId, binding.companyId), eq(issueWorkProducts.issueId, binding.issueId),\n    )) : [];\n    const accessibleProduct = products.some(product => {\n      if (product.createdByRunId !== binding.runId) return false;\n      if ([\"failed\", \"cancelled\", \"archived\"].includes(product.status)) return false;\n      // A workspace_file resource is only a locator: registration neither checks\n      // its current bytes nor keeps them alive after workspace cleanup. Requested\n      // files need a published URL or the verified attachment receipt above.\n      const accessible = typeof product.url === \"string\" && /^https?:\\/\\//iu.test(product.url);\n      return accessible && [product.url, `work_product:${product.id}`, `work-product:${product.id}`, `artifact:${product.id}`]\n        .some(ref => typeof ref === \"string\" && refs.has(ref));\n    });\n    if (!accessibleProduct) throw new Error(\"The requested file has no accessible delivery evidence. Use register_deliverable and cite deliverable:<attachmentId>, or cite an accessible work product registered by this run for this task. Empty evidence, prior-run output, and a verification result cannot substitute for the requested file. Continue publishing or report a concrete blocker; no human completion approval was created.\");\n  }","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/server/src/services/native-runtime/native-deliverable-feedback.ts#L116-L152","documentation":"When completion prose cites something that looks like a local/workspace file path (file: URI, relative/absolute path, drive letter, or a bare filename-like string) for a requested file output or a registered artifact ref, validateNativeDeliverableEvidence rejects it: workspace-only paths are not downloadable by the end user. Deliverables must be registered via register_deliverable so an /api/attachments/<id>/content link exists.","triggerScenarios":"nativeCompletionFeedback / verifyReceipt where refs contain e.g. './report.pdf', '/workspace/out/result.csv', 'file:///tmp/x.png', or 'final-report.pdf' while fileRequested is true or the value is in artifactRefs.","commonSituations":"Agent summarizes completion with a relative path to the produced file; agent lists output filenames without registering them; Windows-style path cited from a Linux workspace.","solutions":["Call register_deliverable for each requested file output and cite deliverable:<attachmentId> from its receipt in the completion text","For repository changes, cite an accessible PR URL or a registered work product instead of a file path","Remove local path references from the completion prose; keep verification commands in the verification field"],"exampleFix":"// before\nOutput saved to ./reports/summary.pdf\n// after\nOutput: deliverable:6a2f4c1e-8b4d-4a2f-9c1e-8b4d4a2f9c1e (download: /api/attachments/6a2f.../content)","handlingStrategy":"validation","validationCode":"const LOCAL_PATH_RE = /^(?:file:|\\.{0,2}\\/|[a-z]:[\\\\/])|^[^\\r\\n]+\\.[a-z0-9]{1,16}(?::\\d+(?::\\d+)?)?$/i;\nif (LOCAL_PATH_RE.test(ref) && (fileRequested || artifactRefs.has(ref))) {\n  throw new Error(\"Cite deliverable:<attachmentId> instead of a workspace path.\");\n}","typeGuard":"const isWorkspacePathRef = (ref) => /^(?:file:|\\.{0,2}\\/|[a-z]:[\\\\/])/i.test(ref) || (!/^[a-z][a-z0-9+.-]*:/i.test(ref) && /\\.[a-z0-9]{1,16}$/i.test(ref));","tryCatchPattern":"try { await feedback(payload); } catch (e) { if (e.message.includes(\"workspace-only file\")) { /* strip local paths, register_deliverable, cite deliverable:<id> */ } else throw e; }","preventionTips":["Never mention raw workspace/relative file paths in completion prose for requested outputs","Convert every requested output file to a deliverable citation before finishing","Use PR links or registered work products for repo changes instead of local diff paths"],"tags":["deliverables","file-paths","ux"],"backgroundTag":"unsupported-operation","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}