different-ai/openwork · error

The local managed MCP vault payload is invalid.

Error message

The local managed MCP vault payload is invalid.

What it means

decryptVault successfully authenticated the envelope's AES-256-GCM tag but the decrypted plaintext either is not valid JSON or fails the isVault shape check, so it throws this plain Error. This means the vault key decrypted the file but the payload content is not a valid vault structure.

Source

Thrown at apps/server/src/local-managed-mcp.ts:311

    return {
      envelope: value.vault,
      index: readVaultIndex(value.index),
      lastRecovery: isVaultRecovery(value.lastRecovery) ? value.lastRecovery : null,
    };
  }
  throw new Error("The local managed MCP vault envelope is invalid.");
}

function decryptVault(envelope: VaultEnvelope, key: Buffer): LocalManagedMcpVault {
  const decipher = createDecipheriv("aes-256-gcm", key, Buffer.from(envelope.iv, "base64"));
  decipher.setAAD(VAULT_AAD);
  decipher.setAuthTag(Buffer.from(envelope.tag, "base64"));
  const plaintext = Buffer.concat([
    decipher.update(Buffer.from(envelope.data, "base64")),
    decipher.final(),
  ]).toString("utf8");
  const value: unknown = JSON.parse(plaintext);
  if (!isVault(value)) throw new Error("The local managed MCP vault payload is invalid.");
  return value;
}

function vaultIndexEntry(connection: StoredLocalManagedMcpConnection): LocalManagedMcpIndexEntry {
  return {
    id: connection.id,
    workspaceId: connection.workspaceId,
    name: connection.name,
    serverUrl: connection.serverUrl,
    enabled: connection.enabled,
    oauth: {
      applicationType: connection.oauth.applicationType,
      ...(connection.oauth.requestedScopes ? { requestedScopes: connection.oauth.requestedScopes } : {}),
      ...(connection.oauth.authorizationServerIssuer ? { authorizationServerIssuer: connection.oauth.authorizationServerIssuer } : {}),
      ...(connection.oauth.clientId ? { clientId: connection.oauth.clientId } : {}),
    },
    status: connection.status,
    ...(connection.lastError === undefined ? {} : { lastError: connection.lastError }),

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Restore the vault from backup or re-initialize it (re-enter stored secrets)
  2. Use the vault recovery flow (lastRecovery / recovery key) to re-seal a fresh vault
  3. Confirm the vault and app versions are compatible — re-run any pending migrations
  4. Check the key being loaded belongs to this vault (a mismatched key usually fails the GCM tag instead, so if you get here the data itself is wrong)

Example fix

// before (data encrypted from wrong payload)
envelope.data = encrypt(JSON.stringify({ foo: 1 }), key);
// after
envelope.data = encrypt(JSON.stringify(buildValidVaultPayload()), key);
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const vault = loadVaultLocked(keyFile);
} catch (error) {
  if (error.message === "The local managed MCP vault payload is invalid.") {
    // key was correct but payload is not a vault: restore from backup or use recovery flow
  }
  throw error;
}

Prevention

When it happens

Trigger: loadVaultLocked decrypts an envelope whose plaintext was overwritten, written by an incompatible schema, or is not the expected JSON vault object.

Common situations: Vault plaintext manually edited while encrypted; a vault file from a different app/version whose key happens to work; plaintext produced by a partially failed migration; someone replaced `data` with encrypted content of an unrelated JSON blob.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/d3fb0c3b4773d257. Report an issue: GitHub.