paperclipai/paperclip · error · SlackAdapterCompatibilityError

file publication receipt lookup is unavailable

Error message

file publication receipt lookup is unavailable

What it means

Even on a Slack endpoint, the runtime needs the adapter's internal paperclipResolveFileUploadReceipt function to perform the metadata-only receipt lookup. If the wired Slack adapter does not define it, a SlackAdapterCompatibilityError is thrown because receipt resolution cannot be served by an adapter lacking that capability.

Source

Thrown at server/src/services/chat-sdk-runtime.ts:2519

    return await slack.paperclipFileUploadReceiptContext.run(
      onUploadAccepted,
      async () => await this.chat.thread(threadId).post(message),
    );
  }

  /** Resolve a previously accepted Slack upload using metadata reads only. */
  async resolveSlackFileUploadReceipt(
    threadId: string,
    fileIds: string[],
  ): Promise<string | null> {
    if (this.provider !== "slack") {
      throw new SlackAdapterCompatibilityError(
        "file publication receipt lookup was called for a non-Slack endpoint",
      );
    }
    const slack = this.adapter as unknown as SlackAdapterInternals;
    if (typeof slack.paperclipResolveFileUploadReceipt !== "function") {
      throw new SlackAdapterCompatibilityError(
        "file publication receipt lookup is unavailable",
      );
    }
    return await slack.paperclipResolveFileUploadReceipt.call(
      this.adapter,
      fileIds,
      threadId,
    );
  }

  /**
   * Persist a Teams activity's authenticated reply route only after the
   * control plane has accepted the callback under the current runtime and
   * credential generation. The route is intentionally separate from the
   * durable provider thread id because Microsoft can move a conversation
   * between regional Bot Connector service URLs.
   */
  async recordMicrosoftTeamsRoute(

View on GitHub (pinned to 01ad858492)

Solutions

  1. Upgrade the Slack adapter to a version exposing paperclipResolveFileUploadReceipt.
  2. Feature-detect the function before calling and treat the receipt as unresolvable (return null) instead of throwing.
  3. Fix test doubles to include paperclipResolveFileUploadReceipt.

Example fix

// before
const path = await runtime.resolveSlackFileUploadReceipt(threadId, fileIds);

// after
const slack = runtime.getProviderAdapter() as {
  paperclipResolveFileUploadReceipt?: unknown;
};
const path = typeof slack.paperclipResolveFileUploadReceipt === "function"
  ? await runtime.resolveSlackFileUploadReceipt(threadId, fileIds)
  : null;
Defensive patterns

Strategy: type-guard

Validate before calling

const slack = runtime.getProviderAdapter() as Record<string, unknown>;
if (typeof slack.paperclipResolveFileUploadReceipt !== "function") return null;

Type guard

function supportsReceiptResolution(a: unknown): a is { paperclipResolveFileUploadReceipt: (fileIds: string[], threadId: string) => Promise<string | null> } {
  return typeof a === "object" && a !== null && typeof (a as any).paperclipResolveFileUploadReceipt === "function";
}

Try / catch

try {
  return await runtime.resolveSlackFileUploadReceipt(threadId, fileIds);
} catch (err) {
  if (err instanceof SlackAdapterCompatibilityError && err.message.includes("lookup is unavailable")) return null;
  throw err;
}

Prevention

When it happens

Trigger: Calling resolveSlackFileUploadReceipt against a Slack runtime whose adapter instance lacks paperclipResolveFileUploadReceipt — typically an outdated adapter version or a partial adapter/test double.

Common situations: Adapter package pinned before the file-receipt lookup feature landed; custom Slack adapters implementing upload but not receipt resolution; tests stubbing the adapter with only a subset of internals.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/1e4c096f313749a0. Report an issue: GitHub.