{"record":{"id":"82ca0ef132e4e9e8","repo":"FlowiseAI/Flowise","slug":"cloudflare-api-token-is-missing-in-credential","errorCode":null,"errorMessage":"Cloudflare API Token is missing in credential.","messagePattern":"Cloudflare API Token is missing in credential\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/components/nodes/chatmodels/ChatCloudflareWorkersAI/ChatCloudflareWorkersAI.ts","lineNumber":64,"sourceCode":"                optional: true,\n                additionalParams: true\n            }\n        ]\n    }\n\n    async init(nodeData: INodeData, _: string, options: ICommonObject): Promise<ChatCloudflareWorkersAI> {\n        const model = nodeData.inputs?.model as string\n        const baseUrl = nodeData.inputs?.baseUrl as string\n\n        const credentialData = await getCredentialData(nodeData.credential ?? '', options)\n        const cloudflareAccountId = getCredentialParam('cloudflareAccountId', credentialData, nodeData)\n        if (!cloudflareAccountId) {\n            throw new Error('Cloudflare Account ID is missing in credential.')\n        }\n\n        const cloudflareApiToken = getCredentialParam('cloudflareApiToken', credentialData, nodeData)\n        if (!cloudflareApiToken) {\n            throw new Error('Cloudflare API Token is missing in credential.')\n        }\n\n        const obj: CloudflareWorkersAIInput = {\n            cloudflareAccountId,\n            cloudflareApiToken,\n            model\n        }\n\n        if (baseUrl) {\n            await checkDenyList(baseUrl)\n            obj.baseUrl = baseUrl\n        }\n\n        const chatModel = new ChatCloudflareWorkersAI(obj)\n        return chatModel\n    }\n}\n","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/components/nodes/chatmodels/ChatCloudflareWorkersAI/ChatCloudflareWorkersAI.ts#L46-L82","documentation":"Thrown by ChatCloudflareWorkersAI.init() (line 64) when getCredentialParam('cloudflareApiToken', credentialData, nodeData) returns a falsy value. Flowise stores per-node secrets inside a credential record resolved via getCredentialData; this guard ensures the Cloudflare Workers AI API token exists before the underlying client is constructed. It runs only after the earlier 'cloudflareAccountId' check passes.","triggerScenarios":"The node's init() runs during chat invocation; getCredentialData resolves a credential object, but the cloudflareApiToken field within that object is undefined, null, or an empty string.","commonSituations":"A Flowise Cloudflare credential component was created/saved with an empty token field, the wrong credential type is bound to the node, or the token was revoked/deleted in the Cloudflare dashboard and the credential was never re-saved.","solutions":["In the Flowise canvas, open the ChatCloudflareWorkersAI node and bind (or re-bind) a Cloudflare credential whose cloudflareApiToken field is populated.","Re-open the credential component, paste a valid Cloudflare API token from Cloudflare dashboard > My Profile > API Tokens, and save.","Confirm cloudflareAccountId is also set on the same credential, since the preceding guard throws if it is missing."],"exampleFix":"// before: credential saved with empty token\n//   cloudflareApiToken: \"\"\n// after: credential saved with a real token\n//   cloudflareApiToken: \"<token-from-cloudflare-dashboard>\"","handlingStrategy":"validation","validationCode":"// Before invoking the node, assert the credential has the token.\nimport { getCredentialData, getCredentialParam } from '../../utils'\n\nasync function assertCloudflareCred(nodeData, options) {\n  const cred = await getCredentialData(nodeData.credential ?? '', options)\n  const token = getCredentialParam('cloudflareApiToken', cred, nodeData)\n  const accountId = getCredentialParam('cloudflareAccountId', cred, nodeData)\n  if (!accountId) throw new Error('cloudflareAccountId missing')\n  if (!token) throw new Error('cloudflareApiToken missing')\n  return { accountId, token }\n}","typeGuard":"type CloudflareCred = { cloudflareAccountId: string; cloudflareApiToken: string }\nfunction isCloudflareCred(c: unknown): c is CloudflareCred {\n  return typeof c === 'object' && c !== null\n    && typeof (c as any).cloudflareAccountId === 'string' && (c as any).cloudflareAccountId !== ''\n    && typeof (c as any).cloudflareApiToken === 'string' && (c as any).cloudflareApiToken !== ''\n}","tryCatchPattern":"try {\n  await chatNode.init(nodeData, '', options)\n} catch (e) {\n  if (e instanceof Error && /Cloudflare API Token is missing/.test(e.message)) {\n    // surface a credential-edit prompt to the user\n  }\n  throw e\n}","preventionTips":["Bind credentials at chatflow build time and run a test chat before publishing.","Use a single shared Cloudflare credential component across nodes so the token lives in one place.","Treat empty-string secrets as missing when saving credential components."],"tags":["credentials","configuration","cloudflare","validation"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}