FlowiseAI/Flowise · error · Error

Number of keys (${keyStrings.length}) does not match number

Error message

Number of keys (${keyStrings.length}) does not match number of group_ids (${groupIds.length})

What it means

Thrown inside MySQLRecordManager.update after groupIds is resolved from updateOptions. The record manager writes one group_id per key, so the arrays must be equal in length. If a caller supplies groupIds explicitly with a different count than keys, the upsert would misalign rows, so it aborts.

Source

Thrown at packages/components/nodes/recordmanager/MySQLRecordManager/MySQLrecordManager.ts:317

        const queryRunner = dataSource.createQueryRunner()
        const tableName = this.sanitizeTableName(this.tableName)

        const updatedAt = await this.getTime()
        const { timeAtLeast, groupIds: _groupIds } = updateOptions ?? {}

        if (timeAtLeast && updatedAt < timeAtLeast) {
            throw new Error(`Time sync issue with database ${updatedAt} < ${timeAtLeast}`)
        }

        // Handle both new format (objects with uid and docId) and old format (strings)
        const isNewFormat = keys.length > 0 && typeof keys[0] === 'object' && 'uid' in keys[0]
        const keyStrings = isNewFormat ? (keys as Array<{ uid: string; docId: string }>).map((k) => k.uid) : (keys as string[])
        const docIds = isNewFormat ? (keys as Array<{ uid: string; docId: string }>).map((k) => k.docId) : keys.map(() => null)

        const groupIds = _groupIds ?? keyStrings.map(() => null)

        if (groupIds.length !== keyStrings.length) {
            throw new Error(`Number of keys (${keyStrings.length}) does not match number of group_ids (${groupIds.length})`)
        }

        const recordsToUpsert = keyStrings.map((key, i) => [key, this.namespace, updatedAt, groupIds[i] ?? null, docIds[i] ?? null])

        const query = `
            INSERT INTO \`${tableName}\` (\`key\`, \`namespace\`, \`updated_at\`, \`group_id\`, \`doc_id\`)
            VALUES (?, ?, ?, ?, ?)
            ON DUPLICATE KEY UPDATE \`updated_at\` = VALUES(\`updated_at\`), \`doc_id\` = VALUES(\`doc_id\`)`

        // To handle multiple files upsert
        try {
            for (const record of recordsToUpsert) {
                // Consider using a transaction for batch operations
                await queryRunner.manager.query(query, record.flat())
            }

            await queryRunner.release()
        } catch (error) {

View on GitHub (pinned to abe4a8601a)

Solutions

  1. Ensure groupIds.length === keys.length before calling update; if you don't need group ids, omit groupIds entirely and the manager defaults each to null.
  2. Zip the two arrays at the source: keys.map((k,i) => ({k, g: groupIds[i]})) and filter together.
  3. If groupIds is optional, pass undefined rather than a mismatched array.

Example fix

// before
await mgr.update(keys, { groupIds: someGroupIds })  // lengths differ
// after
await mgr.update(keys, { groupIds: keys.map((_, i) => groupIds[i] ?? null) })
Defensive patterns

Strategy: validation

Validate before calling

function validateKeysAndGroupIds(keys: unknown[], groupIds?: unknown[]): void {
  if (groupIds && groupIds.length !== keys.length) {
    throw new Error(`groupIds length (${groupIds.length}) must equal keys length (${keys.length})`)
  }
}

Type guard

function areAligned(keys: unknown[], groupIds: unknown[] | undefined): boolean {
  return !groupIds || groupIds.length === keys.length
}

Try / catch

try {
  await manager.update(keys, { groupIds })
} catch (e) {
  if (e instanceof Error && e.message.startsWith('Number of keys')) {
    // drop groupIds and retry, or realign upstream
  }
  throw e
}

Prevention

When it happens

Trigger: Passing updateOptions.groupIds as an array whose length differs from the keys array; passing keys as objects-with-uid but groupIds sized for a different batch; a partial pipeline that filters keys without filtering groupIds.

Common situations: Upstream code slices keys (.slice(0, 10)) but forgets to slice groupIds; merging two sources where one contributed extra keys; off-by-one when zipping keys and groupIds.

Related errors


AI-assisted analysis of FlowiseAI/Flowise@abe4a8601a (2026-08-12). Data as JSON: /api/errors/74a2adcb94b76b16. Report an issue: GitHub.