HeyPuter/puter · error · HttpError

field_required

field_required

Error message

Missing required field: text

What it means

AWSPollyTTSProvider.synthesize requires a non-empty text string. After the engine check, if text is not a string or trims to empty, it throws HTTP 400 (legacyCode field_required) with fields.key='text'. This runs before voice resolution and credit checks.

Source

Thrown at src/backend/drivers/ai-tts/providers/awsPolly/AWSPollyTTSProvider.ts:248

        } = args;

        if (test_mode) {
            return { url: SAMPLE_AUDIO_URL, content_type: 'audio' };
        }

        if (!VALID_ENGINES.includes(engine)) {
            throw new HttpError(
                400,
                `Invalid engine: ${engine}. Valid engines: ${VALID_ENGINES.join(', ')}`,
                {
                    legacyCode: 'invalid_engine',
                    fields: { engine, valid_engines: VALID_ENGINES },
                },
            );
        }

        if (typeof text !== 'string' || text.trim() === '') {
            throw new HttpError(400, 'Missing required field: text', {
                legacyCode: 'field_required',
                fields: { key: 'text' },
            });
        }

        const actor = Context.get('actor')!;
        const usageType = `aws-polly:${engine}:character`;
        const ucentsPerChar = AWS_POLLY_COSTS[engine] ?? 0;
        const totalCost = ucentsPerChar * text.length;

        const usageAllowed = await this.meteringService.hasEnoughCredits(
            actor,
            totalCost,
        );
        if (!usageAllowed) {
            throw new HttpError(402, 'Insufficient funds', {
                legacyCode: 'insufficient_funds',
            });

View on GitHub (pinned to 908ec23eda)

Solutions

  1. Pass a non-empty text string: { text: 'Hello world', provider: 'aws-polly' }.
  2. Validate/trim text on the client before submitting; reject empty input upstream.
  3. If sending SSML, put it in the text field with ssml: true (the provider routes on that flag).

Example fix

// before
await driver.synthesize({ provider: 'aws-polly', engine: 'neural' }); // no text
// after
await driver.synthesize({ text: 'Hello world', provider: 'aws-polly', engine: 'neural' });
Defensive patterns

Strategy: validation

Validate before calling

function synthesizePolly(text, opts = {}) {
  if (typeof text !== 'string' || text.trim() === '') {
    throw new Error('text is required and must be a non-empty string');
  }
  return driver.synthesize({ text, provider: 'aws-polly', ...opts });
}

Type guard

const isNonEmptyString = (v: unknown): v is string =>
  typeof v === 'string' && v.trim().length > 0;

if (isNonEmptyString(text)) {
  await driver.synthesize({ text, provider: 'aws-polly', engine: 'neural' });
}

Prevention

When it happens

Trigger: Calling synthesize with text omitted, null, a number, an empty string, or only whitespace; passing SSML in a separate field while leaving text blank.

Common situations: UI submitting before the user typed anything; passing the prompt into the wrong argument; whitespace-only input from a trimmed textarea; test calls that forget the text field.

Related errors


AI-assisted analysis of HeyPuter/puter@908ec23eda (2026-08-12). Data as JSON: /api/errors/5f9bef20ce28a98e. Report an issue: GitHub.