{"record":{"id":"eb9b0373fdcdff18","repo":"infiniflow/ragflow","slug":"invalid-chat-id-payload-chat-id","errorCode":null,"errorMessage":"Invalid chat_id: ${payload.chat_id}","messagePattern":"Invalid chat_id: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"api/channels/whatsapp/gateway-node/index.js","lineNumber":330,"sourceCode":"        const dropped = this.events.slice(0, this.events.length - 500);\n        this.events = this.events.slice(-500);\n        for (const oldEvent of dropped) {\n          if (oldEvent.kind === 'message' && oldEvent.message_id) {\n            this.messageStore.delete(oldEvent.message_id);\n          }\n        }\n      }\n      this.lastSnapshotAt = now();\n    }\n  }\n\n  async send(payload) {\n    if (!this.sock) {\n      throw new Error('WhatsApp session is not running.');\n    }\n    const jid = normalizeJid(payload.chat_id);\n    if (!jid) {\n      throw new Error(`Invalid chat_id: ${payload.chat_id}`);\n    }\n    const text = String(payload.text || '');\n    const options = {};\n    if (payload.reply_to_message_id) {\n      const quoted = this.messageStore.get(String(payload.reply_to_message_id));\n      if (quoted) {\n        options.quoted = quoted;\n      }\n    }\n    await this.sock.sendMessage(jid, { text }, options);\n    this.lastSnapshotAt = now();\n  }\n\n  async stop() {\n    this.stopping = true;\n    clearTimeout(this.restartTimer);\n    this.restartTimer = null;\n    const sock = this.sock;","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/api/channels/whatsapp/gateway-node/index.js#L312-L348","documentation":"Raised at the top of _fetch_from_gitlab when self.gitlab_client is None — i.e. the connector began ingesting before load_credentials() built a gitlab.Gitlab client. It is a programming/lifecycle error in the caller, not a GitLab-side failure.","triggerScenarios":"Calling load_from_state()/poll_source()/ _fetch_from_gitlab() directly without first calling load_credentials(credentials_dict), or load_credentials returning early on a malformed credential payload so client construction was skipped.","commonSituations":"Test harness instantiating the connector and immediately indexing, orchestrator bug that skips the credential-loading step, credential dict missing the token key so client init was bypassed.","solutions":["Ensure load_credentials() is called (and completes without exception) before any ingestion entry point","Inspect why gitlab_client is still None after load_credentials — usually the credential dict lacks gitlab_access_token / gitlab_instance_url keys","In custom code, assert connector.gitlab_client is not None (or lazily construct it) before calling load_from_state()"],"exampleFix":"# before\nconnector = GitlabConnector(...)\ndocs = connector.load_from_state()  # boom: client never built\n\n# after\nconnector = GitlabConnector(...)\nconnector.load_credentials({\"gitlab_access_token\": tok, \"gitlab_instance_url\": url})\ndocs = connector.load_from_state()","handlingStrategy":"validation","validationCode":"def ready_to_index(connector) -> bool:\n    return connector.gitlab_client is not None\n\n# gate before ingestion\nassert ready_to_index(connector), \"call load_credentials() before indexing\"","typeGuard":"from typing import assert_type\n\ndef has_loaded_client(conn) -> bool:\n    return getattr(conn, \"gitlab_client\", None) is not None","tryCatchPattern":"from common.data_source.exceptions import ConnectorMissingCredentialError\n\ntry:\n    docs = connector.load_from_state()\nexcept ConnectorMissingCredentialError:\n    connector.load_credentials(creds)  # complete lifecycle, then retry once\n    docs = connector.load_from_state()","preventionTips":["Always follow the contract: construct → load_credentials → validate → index","In orchestrators, refuse to schedule jobs for connectors whose credentials never loaded","Unit-test the lifecycle order in CI so regressions surface early"],"tags":["gitlab","lifecycle","credentials","connector","programmer-error"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}