{"record":{"id":"62b878330db6e9bb","repo":"paperclipai/paperclip","slug":"teams-private-state-could-not-be-sealed","errorCode":null,"errorMessage":"Teams private state could not be sealed","messagePattern":"Teams private state could not be sealed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/src/services/chat-teams-file-consent.ts","lineNumber":118,"sourceCode":"async function sealPrivate(\n  context: TeamsFilePrivateContext,\n  purpose: string,\n  value: unknown,\n): Promise<TeamsFileCiphertext> {\n  const parsed = privateContextSchema.safeParse(context);\n  if (!parsed.success) throw new Error(\"Invalid Teams private state\");\n  try {\n    const prepared = await getSecretProvider(\"local_encrypted\").createSecret({\n      value: JSON.stringify({\n        schema: \"paperclip.teams.file-private.v1\",\n        context: parsed.data,\n        purpose,\n        value,\n      }),\n    });\n    return prepared.material;\n  } catch {\n    throw new Error(\"Teams private state could not be sealed\");\n  }\n}\n\nasync function openPrivate(\n  context: TeamsFilePrivateContext,\n  purpose: string,\n  material: TeamsFileCiphertext,\n): Promise<unknown> {\n  try {\n    const parsedContext = privateContextSchema.parse(context);\n    // Bound even corrupted database material before passing it to the provider.\n    if (Buffer.byteLength(JSON.stringify(material)) > 128 * 1024)\n      throw new Error();\n    const plaintext = await getSecretProvider(\"local_encrypted\").resolveVersion(\n      { material, externalRef: null },\n    );\n    if (Buffer.byteLength(plaintext) > 64 * 1024) throw new Error();\n    const envelope = z","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/services/chat-teams-file-consent.ts#L100-L136","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check that the Teams private-state key/secret is configured and present in the environment","Temporarily log inside the catch (or wrap the inner call) to recover the original error — it is currently discarded","Verify the crypto prepare context and purpose strings match what sealPrivate expects after any refactor"],"exampleFix":"// before\n} catch {\n  throw new Error(\"Teams private state could not be sealed\");\n}\n// after\n} catch (error) {\n  throw new Error(\"Teams private state could not be sealed\", { cause: error });\n}","handlingStrategy":"try-catch","validationCode":"if (!privateStateKey || privateStateKey.length < MIN_KEY_BYTES) throw new Error('Teams private state key missing/too short');","typeGuard":null,"tryCatchPattern":"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; }","preventionTips":["Provision and verify Teams sealing keys in every environment at startup","Preserve error.cause when rethrowing (fix the catch clause) so failures are diagnosable","Smoke-test seal/open round-trip after key rotation or refactors"],"tags":["teams","crypto","sealing","opaque-error"],"backgroundTag":"internal-invariant-violation","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}