mastra-ai/mastra · error

Unsupported encryption algorithm: ${prefix}

Error message

Unsupported encryption algorithm: ${prefix}

What it means

decrypt() in channels/slack/src/crypto.ts parses ciphertext of the form 'prefix:salt:iv:authTag:encrypted'. The prefix before the first colon must equal ALGO_PREFIX (the algorithm tag this library encrypts with). A mismatched prefix means the data was not encrypted by this library's encrypt() or was produced by a different/older algorithm version.

Source

Thrown at channels/slack/src/crypto.ts:86

  const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
  const authTag = cipher.getAuthTag();

  return `${ALGO_PREFIX}:${salt.toString('base64')}:${iv.toString('base64')}:${authTag.toString('base64')}:${encrypted.toString('base64')}`;
}

/**
 * Decrypt data produced by encrypt().
 */
export function decrypt(ciphertext: string, key: string): string {
  const colonIdx = ciphertext.indexOf(':');
  if (colonIdx === -1) {
    throw new Error('Invalid ciphertext format');
  }

  const prefix = ciphertext.slice(0, colonIdx);
  if (prefix !== ALGO_PREFIX) {
    throw new Error(`Unsupported encryption algorithm: ${prefix}`);
  }

  const payload = ciphertext.slice(colonIdx + 1);
  const [saltB64, ivB64, authTagB64, encryptedB64] = payload.split(':');
  if (!saltB64 || !ivB64 || !authTagB64 || encryptedB64 === undefined) {
    throw new Error('Invalid ciphertext payload');
  }

  const salt = Buffer.from(saltB64, 'base64');
  const derived = Buffer.from(hkdfSync('sha256', key, salt, 'mastra-slack-encryption', 32));
  const iv = Buffer.from(ivB64, 'base64');
  const authTag = Buffer.from(authTagB64, 'base64');
  const encrypted = Buffer.from(encryptedB64, 'base64');

  const decipher = createDecipheriv('aes-256-gcm', derived, iv);
  decipher.setAuthTag(authTag);
  return Buffer.concat([decipher.update(encrypted), decipher.final()]).toString('utf8');
}

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Re-encrypt the value with the current library's encrypt() so the ciphertext carries the correct ALGO_PREFIX.
  2. Delete/recreate the affected installation or config record so it is written fresh in the current format.
  3. Verify the stored field actually contains ciphertext (should look like '<prefix>:base64:base64:base64:base64'), not a plaintext token.

Example fix

// before (plaintext in storage)
const token = 'xoxb-123-456';
await store.save({ botToken: token });
// after
const token = await crypto.encrypt('xoxb-123-456');
await store.save({ botToken: token });
Defensive patterns

Strategy: validation

Validate before calling

function looksLikeCiphertext(v) {
  if (typeof v !== 'string') return false;
  const [prefix] = v.split(':');
  return Boolean(prefix) && /^[A-Za-z0-9_-]+$/.test(prefix);
}
if (!looksLikeCiphertext(stored)) throw new Error('value is not library-encrypted ciphertext; re-encrypt it');

Type guard

function isCiphertext(v: unknown): v is string {
  return typeof v === 'string' && v.includes(':') && /^[a-z0-9-]+:/i.test(v);
}

Try / catch

try {
  const token = await decrypt(stored);
} catch (err) {
  if (err instanceof Error && err.message.startsWith('Unsupported encryption algorithm')) {
    // value written by different format/version: re-encrypt or re-install
    await reInstallSlackAgent(agentId);
  } else throw err;
}

Prevention

When it happens

Trigger: Calling #decryptPendingInstallation, #decryptInstallation, or #decryptConfigTokens with a stored value whose first colon-delimited segment differs from ALGO_PREFIX — e.g. plaintext stored in a field expected to be ciphertext, values encrypted by another tool, or ciphertext written by an older library version with a different algorithm prefix.

Common situations: Manually inserted or migrated rows in the storage backend; switching encryption keys/formats between versions; accidentally storing an unencrypted token where ciphertext is expected.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/93e7e4a3d7f5731f. Report an issue: GitHub.