mastra-ai/mastra · error
[FactorySecretEncryption] Key id is required.
Error message
[FactorySecretEncryption] Key id is required.
What it means
Factory secret encryption uses AES-256-GCM with envelope encryption keyed by a stable key id (the id is stamped into envelopes so older keys in `previous` can decrypt). validateKey() throws when the configured key's id is empty/missing, because envelopes could not be attributed or rotated without it.
Source
Thrown at mastracode/factory/src/secret-encryption.ts:36
/** Encrypts opaque JSON values before they cross the Factory storage boundary. */
export interface FactorySecretEncryption {
encrypt<T>(value: T): Promise<string>;
decrypt<T>(value: unknown): Promise<DecryptedFactorySecret<T>>;
}
export interface FactorySecretEncryptionKey {
id: string;
key: Uint8Array;
}
export interface FactorySecretEncryptionConfig {
primary: FactorySecretEncryptionKey;
previous?: FactorySecretEncryptionKey[];
}
function validateKey({ id, key }: FactorySecretEncryptionKey): Buffer {
if (!id) throw new Error('[FactorySecretEncryption] Key id is required.');
const buffer = Buffer.from(key);
if (buffer.byteLength !== 32) {
throw new Error(`[FactorySecretEncryption] Key "${id}" must be exactly 32 bytes.`);
}
return buffer;
}
function parseEnvelope(value: string): SecretEnvelopeV1 {
let parsed: unknown;
try {
parsed = JSON.parse(Buffer.from(value.slice(ENVELOPE_PREFIX.length), 'base64url').toString('utf8'));
} catch {
throw new Error('[FactorySecretEncryption] Invalid encrypted value.');
}
if (
!parsed ||
typeof parsed !== 'object' ||View on GitHub (pinned to 75dd419e61)
Solutions
- Set a non-empty id (e.g. 'k-2026-01') on the primary FactorySecretEncryptionKey.
- If the id comes from an env var (e.g. SECRET_KEY_ID), verify it is set in the deployment environment.
- Check that parsed JSON/env config actually populates the id field, not just the key bytes.
- When rotating, ensure both old and new keys retain their original stable ids.
Example fix
// before
createFactorySecretEncryption({
primary: { id: process.env.SECRET_KEY_ID ?? '', key: keyBytes }, // empty id
});
// after
const id = process.env.SECRET_KEY_ID;
if (!id) throw new Error('SECRET_KEY_ID must be set');
createFactorySecretEncryption({ primary: { id, key: keyBytes } }); Defensive patterns
Strategy: validation
Validate before calling
function assertEncryptionKey(cfg: { id?: unknown; key: Uint8Array }): void {
if (!cfg.id || typeof cfg.id !== 'string') throw new Error('SECRET_KEY_ID (key id) must be a non-empty string');
if (Buffer.from(cfg.key).byteLength !== 32) throw new Error('encryption key must be exactly 32 bytes');
}
// run over primary and every previous entry before createFactorySecretEncryption Type guard
function isFactorySecretEncryptionKey(v: unknown): v is { id: string; key: Uint8Array } {
return typeof v === 'object' && v !== null && typeof (v as any).id === 'string' && (v as any).id.length > 0 && (v as any).key instanceof Uint8Array;
} Try / catch
try {
const enc = createFactorySecretEncryption({ primary, previous });
} catch (err) {
if (err instanceof Error && err.message === '[FactorySecretEncryption] Key id is required.') {
console.error('Check SECRET_KEY_ID env var / config: every key needs a stable non-empty id');
} else throw err;
} Prevention
- Fail fast at config-load time: assert every key has both a non-empty id and 32 bytes.
- Validate required encryption env vars at process startup, before handling requests.
- Give keys stable, dated ids (e.g. 'k-2026-01') so rotation keeps decrypting old envelopes.
- Add a startup smoke test that constructs the encryption config in CI.
When it happens
Trigger: Calling createFactorySecretEncryption (directly or via primaryKey) with primary (or a previous entry) whose FactorySecretEncryptionKey.id is undefined, null, or an empty string.
Common situations: Loading keys from env vars where the id var is unset (missing-env-var); building the config programmatically and forgetting the id field; JSON config with an empty id string; a migration/rotation script that copies only the key bytes.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- Cookie password must be at least 32 characters for SSO. Set
- Cookie password must be at least 32 characters for SSO. Set
- Telegram installation secrets are encrypted at rest, but no
- [FactorySecretEncryption] Key "${id}" must be exactly 32 byt
- [FactorySecretEncryption] Unknown key id "${envelope.keyId}"
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/67ae2ccfe442e78e.
Report an issue: GitHub.