Budibase/budibase · error · HTTPError

Automation ID is required to test a saved password

Error message

Automation ID is required to test a saved password

What it means

hydrateEmailConnectionPassword resolves a masked saved IMAP password for testing an email (IMAP) trigger. Because the stored password lives on a saved automation's trigger inputs, a masked password cannot be resolved without knowing which automation to read from, so the request is rejected with HTTP 400.

Source

Thrown at packages/server/src/api/controllers/automation.ts:234

    action: await actionDefs(),
  }
}

async function hydrateEmailConnectionPassword(
  inputs: TestEmailConnectionRequest
): Promise<EmailTriggerInputs> {
  const { automationId, ...emailInputs } = inputs
  if (emailInputs.authType === EmailTriggerAuthType.OAUTH2) {
    delete emailInputs.password
    return emailInputs
  }

  if (!isMaskedPassword(emailInputs.password)) {
    return emailInputs
  }

  if (!automationId) {
    throw new HTTPError(
      "Automation ID is required to test a saved password",
      400
    )
  }

  const automation = await context
    .getWorkspaceDB()
    .tryGet<Automation>(automationId)
  if (!automation) {
    throw new HTTPError("Automation not found", 404)
  }

  const trigger = automation.definition.trigger
  if (!trigger) {
    throw new HTTPError("No trigger found for automation", 400)
  }
  if (!isEmailTrigger(trigger)) {
    throw new HTTPError("Automation trigger is not an email trigger", 400)

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Include automationId in the test request body
  2. Send the real plaintext password instead of the masked value if testing outside an automation context
  3. Fetch the automation first so its ID is available when testing

Example fix

// before
await api.post('/api/automations/email/test', { emailInputs })
// after
await api.post('/api/automations/email/test', { emailInputs, automationId: 'auto_123' })
Defensive patterns

Strategy: validation

Validate before calling

const isMasked = (pw?: string) => !pw || /^[#•*]+$/.test(pw)
if (isMasked(emailInputs.password) && !automationId) {
  throw new Error('automationId is required when using a saved (masked) password')
}

Try / catch

try {
  await testEmailConnection({ emailInputs, automationId })
} catch (e) {
  if (e.status === 400 && e.message.includes('Automation ID is required')) {
    // prompt user to provide the automation or the real password
  }
}

Prevention

When it happens

Trigger: Calling testEmailConnection with emailInputs.password still in masked form (e.g. '####') while the request body omits automationId.

Common situations: Testing an email connection from a generic connection-test UI that isn't tied to a saved automation; copying inputs from a masked GET response without passing the automation ID back.

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29). Data as JSON: /api/errors/151565490b1df049. Report an issue: GitHub.