paperclipai/paperclip · error

Photon sends require an immutable Paperclip publication…

Error message

Photon sends require an immutable Paperclip publication identity

What it means

Photon's postMessage is deliberately unimplemented: it always throws 'Photon sends require an immutable Paperclip publication identity'. Photon messages published through Paperclip need a stable publication identity, and the adapter refuses ad-hoc sends that would break that immutability guarantee.

Solutions

  1. Do not call postMessage on the Photon adapter; treat Photon as read/receipt-only for outbound publication.
  2. Route outbound messages through the Paperclip publication-identity path instead of direct adapter sends.
  3. Feature-check before sending: skip or no-op Photon when the code path requires postMessage.

Example fix

// before
await adapter.postMessage(chatId, message);
// after
if (typeof adapter.postMessage === "function" && adapter.capabilities?.canPost) {
  await adapter.postMessage(chatId, message);
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (adapter === photonAdapter || !adapter.capabilities?.canPost) return; // Photon cannot post

Type guard

const canPost = (a: unknown): a is AdapterWithPost => typeof (a as AdapterWithPost).postMessage === "function" && (a as AdapterWithPost).capabilities?.canPost === true;

Try / catch

try {
  await adapter.postMessage(chatId, msg);
} catch (e) {
  if (e.message.includes("immutable Paperclip publication identity")) return; // Photon: sends unsupported
  throw e;
}

Prevention

When it happens

Trigger: Any call to adapter.postMessage(chatId, message) on the Photon adapter, regardless of arguments.

Common situations: Generic notification or bot code that calls postMessage on every messaging adapter without excluding Photon; attempting to send agent replies through the Photon channel.

Related errors


AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18). Data as JSON: /api/errors/25fee57c00e4637b. Report an issue: GitHub.

Appendix: source

Thrown at server/src/services/photon/adapter.ts:378

      this.typing.delete(id);
      void this.refreshTyping(id, true).catch(() => {});
    }, 8_000);
    timer.unref();
    this.typing.set(id, timer);
  }
  async endTyping(id: string): Promise<void> {
    if (this.typing.has(id)) clearTimeout(this.typing.get(id));
    this.typing.delete(id);
    if (!this.closed)
      await this.client.chats
        .setTyping(this.decodeThreadId(id).chatGuid, false)
        .catch(() => {});
  }
  async postMessage(
    _id: string,
    _message: AdapterPostableMessage,
  ): Promise<never> {
    throw new Error(
      "Photon sends require an immutable Paperclip publication identity",
    );
  }
  async editMessage(
    _id: string,
    _messageId: string,
    _message: AdapterPostableMessage,
  ): Promise<never> {
    throw new Error(
      "Photon edits require an immutable Paperclip publication identity",
    );
  }
  async deleteMessage(): Promise<never> {
    throw new Error("Photon message deletion is not supported");
  }
  async addReaction(): Promise<void> {
    /* Receipt reactions are intentionally not published. */
  }

View on GitHub (pinned to 3f1d897a7c)