FlowiseAI/Flowise · error · Error

Google Generative AI requires alternate messages between…

Error message

Google Generative AI requires alternate messages between authors

What it means

Google Generative AI requires strictly alternating author roles (user/model) in its Content[] payload. This guard fires when the current message's converted role equals the previous content's role AND the reducer is not in a merge-with-previous state. Consecutive same-role messages violate Gemini's conversation contract.

Solutions

  1. Ensure the messages array strictly alternates roles (human, ai, human, ai, ...) before invoking the Google model.
  2. If consecutive same-role messages are intentional, enable system-merge / content-merging so they collapse into one Content entry.
  3. Insert a synthetic assistant message (or remove the duplicate) to restore alternation.
  4. Inspect memory node settings — set a return-by that pairs user/assistant turns (e.g. return both halves of each exchange).

Example fix

// before
messages = [human1, human2, ai1] // two humans in a row -> throws [81]

// after
function enforceAlternation(msgs) {
  const out = []
  let lastRole = null
  for (const m of msgs) {
    const role = getMessageAuthor(m)
    if (role === lastRole && role !== 'system') {
      // merge text into previous same-role message instead of appending
      out[out.length - 1].content += '\n\n' + m.content
      continue
    }
    out.push(m)
    lastRole = role
  }
  return out
}
await model.invoke(enforceAlternation(messages))
Defensive patterns

Strategy: validation

Validate before calling

function assertAlternateAuthors(messages) {
  let last = null
  for (const m of messages) {
    const role = convertAuthorToRole(getMessageAuthor(m))
    if (last === role && role !== 'system') {
      throw new Error(`Consecutive ${role} messages will be rejected by Google`)
    }
    last = role
  }
}
assertAlternateAuthors(messages)
await model.invoke(messages)

Type guard

function isConsecutiveSameRole(messages: BaseMessage[]): boolean {
  let last = ''
  for (const m of messages) {
    const r = convertAuthorToRole(getMessageAuthor(m))
    if (r === last && r !== 'system') return true
    last = r
  }
  return false
}

Try / catch

try {
  await model.invoke(messages)
} catch (e) {
  if (e.message.includes('alternate messages')) {
    await model.invoke(mergeConsecutiveSameRole(messages))
  } else throw e
}

Prevention

When it happens

Trigger: Two HumanMessages back-to-back, two AIMessages back-to-back, or a function/tool message that maps to 'user' immediately following a 'user' message — without mergeWithPreviousContent being set to absorb the duplicate role. Also triggered by chat memory that appends repeated user turns without an assistant reply in between.

Common situations: Memory buffers that store unpaired user messages (user sent multiple inputs before a reply); tool-calling flows where consecutive AI tool-call messages are not separated by tool-result messages; merged chatflows combining two user inputs without an assistant bridge; OpenAI->Gemini migration since OpenAI is lenient about repeated roles.

Related errors


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

Appendix: source

Thrown at packages/components/nodes/chatmodels/ChatGoogleGenerativeAI/FlowiseChatGoogleGenerativeAI.ts:423

    model?: string
) {
    return messages.reduce<{
        content: Content[]
        mergeWithPreviousContent: boolean
    }>(
        (acc, message, index) => {
            if (!BaseMessage.isInstance(message)) {
                throw new Error('Unsupported message input')
            }
            const author = getMessageAuthor(message)
            if (author === 'system' && index !== 0) {
                throw new Error('System message should be the first one')
            }
            const role = convertAuthorToRole(author)

            const prevContent = acc.content[acc.content.length]
            if (!acc.mergeWithPreviousContent && prevContent && prevContent.role === role) {
                throw new Error('Google Generative AI requires alternate messages between authors')
            }

            const parts = convertMessageContentToParts(message, isMultimodalModel, messages.slice(0, index), model)

            if (acc.mergeWithPreviousContent) {
                const prevContent = acc.content[acc.content.length - 1]
                if (!prevContent) {
                    throw new Error('There was a problem parsing your system message. Please try a prompt without one.')
                }
                prevContent.parts.push(...parts)

                return {
                    mergeWithPreviousContent: false,
                    content: acc.content
                }
            }
            let actualRole = role
            if (actualRole === 'function' || (actualRole === 'system' && !convertSystemMessageToHumanContent)) {

View on GitHub (pinned to abe4a8601a)