mastra-ai/mastra · error

Version number ${input.versionNumber} already exists for MCP

Error message

Version number ${input.versionNumber} already exists for MCP client ${input.mcpClientId}

What it means

`createVersion` also enforces uniqueness of the (mcpClientId, versionNumber) pair: the same client cannot have two versions with the same number. Thrown after the id check when scanning existing versions finds a match.

Source

Thrown at packages/core/src/storage/domains/mcp-clients/inmemory.ts:186

      perPage: perPageForResponse,
      hasMore: offset + perPage < clonedConfigs.length,
    };
  }

  // ==========================================================================
  // MCP Client Version Methods
  // ==========================================================================

  async createVersion(input: CreateMCPClientVersionInput): Promise<MCPClientVersion> {
    // Check if version with this ID already exists
    if (this.db.mcpClientVersions.has(input.id)) {
      throw new Error(`Version with id ${input.id} already exists`);
    }

    // Check for duplicate (mcpClientId, versionNumber) pair
    for (const version of this.db.mcpClientVersions.values()) {
      if (version.mcpClientId === input.mcpClientId && version.versionNumber === input.versionNumber) {
        throw new Error(`Version number ${input.versionNumber} already exists for MCP client ${input.mcpClientId}`);
      }
    }

    const version: MCPClientVersion = {
      ...input,
      createdAt: new Date(),
    };

    // Deep clone before storing
    this.db.mcpClientVersions.set(input.id, this.deepCopyVersion(version));
    return this.deepCopyVersion(version);
  }

  async getVersion(id: string): Promise<MCPClientVersion | null> {
    const version = this.db.mcpClientVersions.get(id);
    return version ? this.deepCopyVersion(version) : null;
  }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Query existing versions via `listVersions` and use max(existing)+1 as the next versionNumber.
  2. Catch this error and treat it as idempotent success if the version content is identical.
  3. Serialize publish operations (lock/queue) to avoid concurrent duplicate numbers.

Example fix

// before
await mcpClients.createVersion({ id, mcpClientId: clientId, versionNumber: nextNumber });
// after
const { versions } = await mcpClients.listVersions(clientId);
const nextNumber = Math.max(0, ...versions.map(v => v.versionNumber)) + 1;
await mcpClients.createVersion({ id, mcpClientId: clientId, versionNumber: nextNumber });
Defensive patterns

Strategy: validation

Validate before calling

const { versions } = await mcpClients.listVersions(mcpClientId, { perPage: false });
if (versions.some(v => v.versionNumber === versionNumber)) {
  throw new Error(`Version number ${versionNumber} already published for ${mcpClientId}`);
}

Try / catch

try {
  await mcpClients.createVersion(input);
} catch (err) {
  if (err instanceof Error && /Version number .* already exists/.test(err.message)) {
    return; // treat as idempotent publish
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling `createVersion` with a `versionNumber` that already exists for the given `mcpClientId`, regardless of version id — e.g., publishing version 2 twice for the same client.

Common situations: A version counter that isn't persisted or incremented correctly across runs; concurrent publishes racing to claim the same next number; replaying an import that assigns numbers from scratch.

Related errors


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