different-ai/openwork · error

Failed to copy attachment "${metadata.filename}" into this w

Error message

Failed to copy attachment "${metadata.filename}" into this worker workspace: expected ${file.size} bytes, wrote ${result.bytes}

What it means

After a successful upload the client verifies the server wrote exactly file.size bytes. A mismatch means a partial or corrupted write, so it throws this error with the expected vs actual byte counts. This protects tools from operating on truncated attachment copies.

Source

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

      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 [
    attachmentPathNotePart(uploaded),
    ...(await Promise.all(uploaded.map(uploadedAttachmentFilePart))),
  ];

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Retry the upload to get a clean full write.
  2. Compare the source file on disk with the stored copy; re-attach if the file changed since attach time.
  3. Investigate the server storage layer for truncation of large files or transformations.

Example fix

// after uploadInbox resolves: if (result.bytes !== file.size) { console.error(`Upload truncated: expected ${file.size}, got ${result.bytes}`); } // then retry
Defensive patterns

Strategy: retry

Validate before calling

const size = attachment.file.size; if (size !== attachment.sizeAtAttach) { showToast(`"${attachment.filename}" changed since attach — re-attach it`); return; }

Try / catch

try { await composerAttachmentsToWorkspaceFileParts({ attachments, endpoint, sessionId, workspaceRoot }); } catch (e) { if (String(e.message).includes('bytes')) { await retryWithBackoff(() => sendWithAttachments()); } else { throw e; } }

Prevention

When it happens

Trigger: uploadInbox returns result.bytes !== file.size — interrupted transfer still reported success, server-side truncation, encoding/transformation of the file during storage, or a stale size from a re-encoded image.

Common situations: Flaky network with a lossy upload pipeline; server storage layer truncating large files; the file changed on disk between read and upload so sizes disagree.

Related errors


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