bmad-code-org/BMAD-METHOD · error · TypeError

Async validation is not supported by @clack/prompts. Please

Error message

Async validation is not supported by @clack/prompts. Please use synchronous validation.

What it means

Thrown (as TypeError) inside the input-prompt wrapper when a question's validate callback returns a Promise. @clack/prompts' text() calls validate synchronously per keystroke; the wrapper detects a Promise return and converts it to a TypeError so the failure is loud instead of silently passing validation (the Promise would never be awaited).

Source

Thrown at tools/installer/prompts.js:701

    // Handle conditional questions via 'when' property
    if (when !== undefined) {
      const shouldAsk = typeof when === 'function' ? await when(answers) : when;
      if (!shouldAsk) continue;
    }

    let answer;

    switch (type) {
      case 'input': {
        // Note: @clack/prompts doesn't support async validation, so validate must be sync
        answer = await text({
          message,
          default: typeof defaultValue === 'function' ? defaultValue(answers) : defaultValue,
          validate: validate
            ? (val) => {
                const result = validate(val, answers);
                if (result instanceof Promise) {
                  throw new TypeError('Async validation is not supported by @clack/prompts. Please use synchronous validation.');
                }
                return result === true ? undefined : result;
              }
            : undefined,
        });
        break;
      }

      case 'confirm': {
        answer = await confirm({
          message,
          default: typeof defaultValue === 'function' ? defaultValue(answers) : defaultValue,
        });
        break;
      }

      case 'list': {
        answer = await select({

View on GitHub (pinned to b70486b9bd)

Solutions

  1. Make the validator synchronous: replace async with a sync function and use sync APIs (fs.pathExistsSync) or pre-computed state captured in closure.
  2. If the check is inherently async, perform it before the prompt and pass the result in, or validate after the prompt returns.
  3. Move expensive checks into a when predicate or a pre-prompt step that runs once.

Example fix

// before
//   { type: 'input', name: 'path', message: 'Path:',
//     validate: async (val) => (await fs.pathExists(val)) || 'Not found' }
//
// after
//   { type: 'input', name: 'path', message: 'Path:',
//     validate: (val) => fs.pathExistsSync(val) || 'Not found' }
Defensive patterns

Strategy: validation

Validate before calling

function assertSyncValidators(questions) {
  for (const q of questions) {
    if (q.type === 'input' && typeof q.validate === 'function' && q.validate.constructor.name === 'AsyncFunction') {
      throw new Error(`Validator for '${q.name}' is async; @clack/prompts requires sync.`);
    }
  }
}
assertSyncValidators(questions);

Type guard

function isSyncValidator(fn) {
  return typeof fn === 'function' && fn.constructor.name !== 'AsyncFunction';
}

Try / catch

try {
  answers = await getClack(questions);
} catch (e) {
  if (/Async validation is not supported/.test(e.message)) {
    // rewrite the offending validator to be sync and retry, or pre-validate inputs
  } else { throw e; }
}

Prevention

When it happens

Trigger: Defining a prompt question with type:'input' and a validate function declared async or returning a Promise — e.g. validate: async (val) => await fs.pathExists(val).

Common situations: Migrating from inquirer (which supports async validate) to @clack/prompts; reusing an async validator across prompt libraries; validating against the filesystem/network inside the prompt.

Related errors


AI-assisted analysis of bmad-code-org/BMAD-METHOD@b70486b9bd (2026-08-13). Data as JSON: /api/errors/8a83806dbabf8d80. Report an issue: GitHub.