different-ai/openwork · error

Workspace endpoint is unavailable; attachments could not be

Error message

Workspace endpoint is unavailable; attachments could not be copied for tool access.

What it means

composerAttachmentsToWorkspaceFileParts requires a workspace endpoint carrying both a client and a workspaceId to upload attachment files into the worker inbox. When input.endpoint.workspaceId is empty/whitespace it throws this error; attachments cannot be copied for tool access without a valid endpoint.

Source

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

}

export async function composerAttachmentsToWorkspaceFileParts(input: {
  attachments: ComposerAttachment[];
  endpoint: ChatAttachmentWorkspaceEndpoint;
  sessionId: string;
  workspaceRoot: string;
  createId?: () => string;
}): Promise<Array<TextPartInput | FilePartInput>> {
  if (input.attachments.length === 0) return [];

  const workspaceRoot = input.workspaceRoot.trim();
  if (!workspaceRoot) {
    throw new Error("Workspace path is unavailable; attachments could not be copied for tool access.");
  }

  const workspaceId = input.endpoint.workspaceId.trim();
  if (!workspaceId) {
    throw new Error("Workspace endpoint is unavailable; attachments could not be copied for tool access.");
  }

  const uploaded: UploadedChatAttachment[] = [];
  for (const attachment of input.attachments) {
    // Oversized images are re-encoded here, at send time, so the composer chip
    // appears instantly at attach time and the canvas work happens while the
    // chip already shows its uploading state. When the transport uploads the
    // original file from its local path, re-encoding would detach that path,
    // so the original bytes are sent instead.
    const file = input.endpoint.client.uploadInboxPrefersOriginalFile?.(attachment.file)
      ? attachment.file
      : await compressImageFile(attachment.file);
    const metadata = resolveAttachmentFileMetadata(file);
    const id = input.createId ? input.createId() : randomAttachmentId();
    const inboxPath = buildChatAttachmentInboxPath({
      sessionId: input.sessionId,
      filename: metadata.filename,
      id,

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Ensure the workspace endpoint (including workspaceId) is fully provisioned before sending messages with attachments.
  2. Re-resolve the endpoint for the current workspace and retry.
  3. Catch the error and inform the user the workspace endpoint is unavailable and to re-open the workspace.

Example fix

// before: await composerAttachmentsToWorkspaceFileParts({ attachments, endpoint, ... }) | // after: if (!endpoint?.workspaceId?.trim()) throw new Error('Workspace not ready'); await composerAttachmentsToWorkspaceFileParts({ attachments, endpoint, ... })
Defensive patterns

Strategy: validation

Validate before calling

if (!endpoint?.workspaceId?.trim()) { showToast('Workspace endpoint is not ready; cannot attach files'); return; } await composerAttachmentsToWorkspaceFileParts({ attachments, endpoint, workspaceRoot, sessionId });

Type guard

function hasWorkspaceEndpoint(endpoint: { workspaceId: string } | null | undefined): endpoint is { workspaceId: string } { return !!endpoint && endpoint.workspaceId.trim().length > 0; }

Try / catch

try { await composerAttachmentsToWorkspaceFileParts({ attachments, endpoint, workspaceRoot, sessionId }); } catch (e) { if (String(e.message).includes('Workspace endpoint is unavailable')) { await reprovisionEndpoint(); } else { throw e; } }

Prevention

When it happens

Trigger: Calling composerAttachmentsToWorkspaceFileParts with an endpoint whose workspaceId is '' or whitespace — e.g. endpoint derived before workspace provisioning completed, or a draft restored for a workspace that no longer exists.

Common situations: Sending an attachment-laden draft after the workspace was deleted or re-created with a new id; endpoint built from an incomplete workspace record; offline/cloud mode where workspaceId is not yet assigned.

Related errors


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