paperclipai/paperclip · error · TeamsAdapterCompatibilityError

invalid file-card shape

Error message

invalid file-card shape

What it means

paperclipSendFileCard validates its input with parseTeamsFileConsentCard (for kind 'consent') or parseTeamsUploadedFileCard (for kind 'file_info'). If the kind is neither, or the input fails the parser's shape requirements, the card cannot be turned into a valid Teams attachment, so this compatibility error is thrown before any network call.

Source

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

  if (enableFileConsent) {
    if (
      typeof teams.app.send !== "function" ||
      typeof teams.app.on !== "function"
    ) {
      throw new TeamsAdapterCompatibilityError(
        "file-consent App hooks are unavailable",
      );
    }
    teams.paperclipSendFileCard = async (threadId, kind, input) => {
      const card =
        kind === "consent"
          ? parseTeamsFileConsentCard(input)
          : kind === "file_info"
            ? parseTeamsUploadedFileCard(input)
            : null;
      if (!card)
        throw new TeamsAdapterCompatibilityError("invalid file-card shape");
      const decoded = teams.decodeThreadId!(threadId);
      // Never infer personal scope from a missing type or conversation prefix.
      if (
        decoded.conversationType !== "personal" ||
        typeof decoded.conversationId !== "string" ||
        !decoded.conversationId ||
        decoded.conversationId.length > 1024 ||
        /[\x00-\x20\x7f]/.test(decoded.conversationId) ||
        /;messageid=/i.test(decoded.conversationId)
      ) {
        throw new TeamsServiceUrlValidationError(
          "Teams file cards require an exact personal conversation",
        );
      }
      return await withThreadServiceUrl(
        threadId,
        async () => {
          let result: unknown;

View on GitHub (pinned to 01ad858492)

Solutions

  1. Validate the kind argument is exactly 'consent' or 'file_info' before calling.
  2. Run the input through the same parser (parseTeamsFileConsentCard/parseTeamsUploadedFileCard) at the call site to see which required field is missing.
  3. Fix the upstream producer so the card payload includes all required fields (name, uploadUrl/acceptContext for consent; fileId/name/contentUrl for file_info).
  4. Add a unit test feeding representative payloads into paperclipSendFileCard to catch shape drift.

Example fix

// before
await teams.paperclipSendFileCard(threadId, 'consent', { foo: 1 }); // invalid shape
// after
await teams.paperclipSendFileCard(threadId, 'consent', {
  name: 'report.pdf',
  uploadUrl: uploadCtx.uploadUrl,
  contentUrl: uploadCtx.contentUrl,
  acceptContext: { threadId }
});
Defensive patterns

Strategy: validation

Validate before calling

const card = kind === 'consent' ? parseTeamsFileConsentCard(input) : kind === 'file_info' ? parseTeamsUploadedFileCard(input) : null;
if (!card) throw new Error(`Invalid ${kind} file-card payload`);

Type guard

function isFileCardKind(k: string): k is 'consent' | 'file_info' {
  return k === 'consent' || k === 'file_info';
}

Try / catch

try {
  await teams.paperclipSendFileCard(threadId, kind, input);
} catch (err) {
  if (err instanceof TeamsAdapterCompatibilityError && err.message === 'invalid file-card shape') {
    logger.error(`Rejected ${kind} file card payload: ${JSON.stringify(input).slice(0, 200)}`);
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling teams.paperclipSendFileCard(threadId, kind, input) with kind not in {'consent','file_info'}, or input missing fields the parsers require (e.g. no name/acceptContext for consent, no fileId/name for file_info), or input being null/undefined.

Common situations: A typo'd kind string ('consentCard' instead of 'consent'); a caller passing the raw upload result instead of the parsed card payload; schema drift after changing the upstream file metadata producer so required fields disappear.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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