{"record":{"id":"20e46cb2b6abff0f","repo":"Budibase/budibase","slug":"oauth2-connection-is-required","errorCode":null,"errorMessage":"OAuth2 connection is required","messagePattern":"OAuth2 connection is required","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/server/src/automations/email/utils/getClient.ts","lineNumber":78,"sourceCode":"    }\n  }\n\n  const legacyId = (inputs as EmailTriggerInputs & { oauth2ConfigId?: string })\n    .oauth2ConfigId\n  if (legacyId) {\n    return { datasourceId: legacyId, authConfigId: legacyId }\n  }\n\n  return null\n}\n\nconst getAuthConfig = async (inputs: EmailTriggerInputs) => {\n  const authType = inputs.authType || EmailTriggerAuthType.PASSWORD\n\n  if (authType === EmailTriggerAuthType.OAUTH2) {\n    const oauth2Ids = resolveOAuth2Ids(inputs)\n    if (!oauth2Ids) {\n      throw new Error(\"OAuth2 connection is required\")\n    }\n    const accessToken = await getOAuth2AccessToken(\n      oauth2Ids.datasourceId,\n      oauth2Ids.authConfigId\n    )\n    return {\n      user: inputs.username,\n      accessToken,\n    }\n  }\n\n  if (!inputs.password) {\n    throw new Error(\"IMAP password is required\")\n  }\n\n  return {\n    user: inputs.username,\n    pass: inputs.password,","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/automations/email/utils/getClient.ts#L60-L96","documentation":"getAuthConfig builds credentials for the email (IMAP) automation trigger. When the configured authType is OAuth2, it resolves datasourceId/authConfigId from the inputs; if those IDs cannot be resolved it means no OAuth2 connection was actually supplied, so it throws instead of attempting an OAuth flow with missing configuration.","triggerScenarios":"An email trigger automation is configured with authType=OAUTH2 but resolveOAuth2Ids(inputs) returns null — i.e. the inputs lack the required OAuth2 datasourceId or authConfigId references.","commonSituations":"Switching an automation from password to OAuth2 auth without selecting an OAuth2 datasource/connection in the builder; inputs partially copied or exported without the connection IDs; API/automation-definition edits that omit auth config fields.","solutions":["Open the automation's email trigger config and select an OAuth2 connection so datasourceId and authConfigId are present in inputs","Check the automation definition JSON for the OAuth2 datasourceId/authConfigId fields and add them","If OAuth2 is not intended, change authType back to PASSWORD and supply a password","Verify the OAuth2 datasource referenced still exists and was not deleted"],"exampleFix":"// before\n{ \"authType\": \"OAUTH2\" } // no connection ids\n// after\n{ \"authType\": \"OAUTH2\", \"datasourceId\": \"ds_...,\", \"authConfigId\": \"cfg_...\" }","handlingStrategy":"validation","validationCode":"const needsOAuth2 = inputs.authType === EmailTriggerAuthType.OAUTH2\nif (needsOAuth2 && !(inputs.datasourceId && inputs.authConfigId)) {\n  throw new Error(\"Configure an OAuth2 connection before enabling OAuth2 auth\")\n}","typeGuard":"function hasOAuth2Ids(inputs: EmailTriggerInputs): inputs is EmailTriggerInputs & { datasourceId: string, authConfigId: string } {\n  return typeof inputs.datasourceId === \"string\" && inputs.datasourceId.length > 0 &&\n         typeof inputs.authConfigId === \"string\" && inputs.authConfigId.length > 0\n}","tryCatchPattern":null,"preventionTips":["Always pair authType=OAUTH2 with a selected connection in the builder UI","Validate automation definitions after export/import","Don't hand-edit auth fields in automation JSON"],"tags":["oauth2","email","automation","config"],"backgroundTag":"missing-oauth2-credentials","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}