different-ai/openwork · error

Failed to copy attachment

Error message

Failed to copy attachment "${metadata.filename}" into this worker workspace: upload did not return a path

What it means

If uploadInbox reports success (result.ok !== false) but returns an empty/whitespace result.path, the client cannot reference the uploaded file, so it throws this error. This guards against a malformed success response where the stored file path is missing.

Solutions

  1. Fix or upgrade the server so uploadInbox always returns the stored inbox path on success.
  2. Verify no proxy/middleware is dropping the path field from the response.
  3. Retry the upload; if reproducible, log the raw response for a bug report.

Example fix

// after uploadInbox resolves: if (!result.path?.trim()) { console.error('uploadInbox response missing path', result); } // report server bug
Defensive patterns

Strategy: type-guard

Type guard

function hasUploadPath(result: { ok?: boolean; path?: string }): result is { ok?: boolean; path: string } { return typeof result.path === 'string' && result.path.trim().length > 0; }

Try / catch

try { await composerAttachmentsToWorkspaceFileParts({ attachments, endpoint, sessionId, workspaceRoot }); } catch (e) { if (String(e.message).includes('upload did not return a path')) { reportServerBug(e); } else { throw e; } }

Prevention

When it happens

Trigger: Server returns a success envelope without a path — e.g. a server bug, a proxy stripping the response body field, or a protocol version mismatch where the path is under a different key.

Common situations: Running a newer client against an older server (or vice versa) that omits 'path'; custom server implementations of uploadInbox that forget to return the path.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/ffd1df521dada12a. Report an issue: GitHub.

Appendix: source

Thrown at apps/app/src/react-app/domains/session/sync/attachment-file-part.ts:384

    const id = input.createId ? input.createId() : randomAttachmentId();
    const inboxPath = buildChatAttachmentInboxPath({
      sessionId: input.sessionId,
      filename: metadata.filename,
      id,
    });

    let result: InboxUploadResult;
    try {
      result = await input.endpoint.client.uploadInbox(workspaceId, file, { path: inboxPath });
    } catch (error) {
      throw new Error(uploadErrorMessage(metadata.filename, error));
    }

    if (result.ok === false) {
      throw new Error(`Failed to copy attachment "${metadata.filename}" into this worker workspace: upload was rejected`);
    }
    if (!result.path.trim()) {
      throw new Error(`Failed to copy attachment "${metadata.filename}" into this worker workspace: upload did not return a path`);
    }
    if (result.bytes !== file.size) {
      throw new Error(`Failed to copy attachment "${metadata.filename}" into this worker workspace: expected ${file.size} bytes, wrote ${result.bytes}`);
    }

    const workspacePath = workspaceInboxPath(result.path);
    const absolutePath = joinWorkspaceRelativePath(workspaceRoot, workspacePath);
    uploaded.push({
      filename: metadata.filename,
      mime: metadata.mime,
      bytes: result.bytes,
      workspacePath,
      url: toFileUrl(absolutePath),
      file,
    });
  }

  return [

View on GitHub (pinned to 2b7df46e8a)