paperclipai/paperclip · error

Teams private state could not be sealed

Error message

Teams private state could not be sealed

What it means

sealPrivate encrypts/MACs Teams private state (a purpose/value pair) through a prepared crypto context; any failure inside the try block is swallowed and rethrown as this opaque error, discarding the original cause. It is called when sealing Teams file-consent bindings, so binding persistence fails if private-state sealing fails.

Source

Thrown at server/src/services/chat-teams-file-consent.ts:118

async function sealPrivate(
  context: TeamsFilePrivateContext,
  purpose: string,
  value: unknown,
): Promise<TeamsFileCiphertext> {
  const parsed = privateContextSchema.safeParse(context);
  if (!parsed.success) throw new Error("Invalid Teams private state");
  try {
    const prepared = await getSecretProvider("local_encrypted").createSecret({
      value: JSON.stringify({
        schema: "paperclip.teams.file-private.v1",
        context: parsed.data,
        purpose,
        value,
      }),
    });
    return prepared.material;
  } catch {
    throw new Error("Teams private state could not be sealed");
  }
}

async function openPrivate(
  context: TeamsFilePrivateContext,
  purpose: string,
  material: TeamsFileCiphertext,
): Promise<unknown> {
  try {
    const parsedContext = privateContextSchema.parse(context);
    // Bound even corrupted database material before passing it to the provider.
    if (Buffer.byteLength(JSON.stringify(material)) > 128 * 1024)
      throw new Error();
    const plaintext = await getSecretProvider("local_encrypted").resolveVersion(
      { material, externalRef: null },
    );
    if (Buffer.byteLength(plaintext) > 64 * 1024) throw new Error();
    const envelope = z

View on GitHub (pinned to 01ad858492)

Solutions

  1. Check that the Teams private-state key/secret is configured and present in the environment
  2. Temporarily log inside the catch (or wrap the inner call) to recover the original error — it is currently discarded
  3. Verify the crypto prepare context and purpose strings match what sealPrivate expects after any refactor

Example fix

// before
} catch {
  throw new Error("Teams private state could not be sealed");
}
// after
} catch (error) {
  throw new Error("Teams private state could not be sealed", { cause: error });
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!privateStateKey || privateStateKey.length < MIN_KEY_BYTES) throw new Error('Teams private state key missing/too short');

Try / catch

try { const material = sealTeamsFileConsentBinding(binding, ctx); } catch (err) { if ((err as Error).message === 'Teams private state could not be sealed') { alertSecretsMisconfigured(); return null; } throw err; }

Prevention

When it happens

Trigger: Key material missing or malformed (unavailable secrets store, wrong key length), the prepare/seal primitive throwing (bad algorithm config, corrupt context), or environment crypto failures during createTeamsFileConsentBinding/seal flows.

Common situations: Missing or rotated encryption keys in a new environment; NODE_ENV/config change pointing at an empty secrets store; platform without required crypto support; a refactor changed the private-context shape expected by the sealer.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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