{"record":{"id":"7206eb9fbf6b2d1d","repo":"FlowiseAI/Flowise","slug":"google-generative-ai-requires-alternate-messages-b","errorCode":null,"errorMessage":"Google Generative AI requires alternate messages between authors","messagePattern":"Google Generative AI requires alternate messages between authors","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/components/nodes/chatmodels/ChatGoogleGenerativeAI/FlowiseChatGoogleGenerativeAI.ts","lineNumber":423,"sourceCode":"    model?: string\n) {\n    return messages.reduce<{\n        content: Content[]\n        mergeWithPreviousContent: boolean\n    }>(\n        (acc, message, index) => {\n            if (!BaseMessage.isInstance(message)) {\n                throw new Error('Unsupported message input')\n            }\n            const author = getMessageAuthor(message)\n            if (author === 'system' && index !== 0) {\n                throw new Error('System message should be the first one')\n            }\n            const role = convertAuthorToRole(author)\n\n            const prevContent = acc.content[acc.content.length]\n            if (!acc.mergeWithPreviousContent && prevContent && prevContent.role === role) {\n                throw new Error('Google Generative AI requires alternate messages between authors')\n            }\n\n            const parts = convertMessageContentToParts(message, isMultimodalModel, messages.slice(0, index), model)\n\n            if (acc.mergeWithPreviousContent) {\n                const prevContent = acc.content[acc.content.length - 1]\n                if (!prevContent) {\n                    throw new Error('There was a problem parsing your system message. Please try a prompt without one.')\n                }\n                prevContent.parts.push(...parts)\n\n                return {\n                    mergeWithPreviousContent: false,\n                    content: acc.content\n                }\n            }\n            let actualRole = role\n            if (actualRole === 'function' || (actualRole === 'system' && !convertSystemMessageToHumanContent)) {","sourceCodeStart":405,"sourceCodeEnd":441,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/components/nodes/chatmodels/ChatGoogleGenerativeAI/FlowiseChatGoogleGenerativeAI.ts#L405-L441","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure the messages array strictly alternates roles (human, ai, human, ai, ...) before invoking the Google model.","If consecutive same-role messages are intentional, enable system-merge / content-merging so they collapse into one Content entry.","Insert a synthetic assistant message (or remove the duplicate) to restore alternation.","Inspect memory node settings — set a return-by that pairs user/assistant turns (e.g. return both halves of each exchange)."],"exampleFix":"// before\nmessages = [human1, human2, ai1] // two humans in a row -> throws [81]\n\n// after\nfunction enforceAlternation(msgs) {\n  const out = []\n  let lastRole = null\n  for (const m of msgs) {\n    const role = getMessageAuthor(m)\n    if (role === lastRole && role !== 'system') {\n      // merge text into previous same-role message instead of appending\n      out[out.length - 1].content += '\\n\\n' + m.content\n      continue\n    }\n    out.push(m)\n    lastRole = role\n  }\n  return out\n}\nawait model.invoke(enforceAlternation(messages))","handlingStrategy":"validation","validationCode":"function assertAlternateAuthors(messages) {\n  let last = null\n  for (const m of messages) {\n    const role = convertAuthorToRole(getMessageAuthor(m))\n    if (last === role && role !== 'system') {\n      throw new Error(`Consecutive ${role} messages will be rejected by Google`)\n    }\n    last = role\n  }\n}\nassertAlternateAuthors(messages)\nawait model.invoke(messages)","typeGuard":"function isConsecutiveSameRole(messages: BaseMessage[]): boolean {\n  let last = ''\n  for (const m of messages) {\n    const r = convertAuthorToRole(getMessageAuthor(m))\n    if (r === last && r !== 'system') return true\n    last = r\n  }\n  return false\n}","tryCatchPattern":"try {\n  await model.invoke(messages)\n} catch (e) {\n  if (e.message.includes('alternate messages')) {\n    await model.invoke(mergeConsecutiveSameRole(messages))\n  } else throw e\n}","preventionTips":["Pair every user turn with an assistant turn in memory buffers.","Validate alternation with a lint helper before each invoke.","Avoid concatenating two user inputs without an assistant bridge.","When tool-calling, always interleave tool-result messages between AI tool-call messages."],"tags":["google-generative-ai","message-ordering","alternation","gemini","chat-memory"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}