HeyPuter/puter · error · HttpError

bad_request

bad_request

Error message

`message` is required

What it means

Returned (HTTP 400, legacy code bad_request) by POST /contactUs on the api subdomain (SystemController). The route requires req.body.message to be a non-empty string. It is gated behind requireUserActor + allowFullAccessToken and a 10-per-15-minutes per-user rate limit.

Source

Thrown at src/backend/controllers/system/SystemController.js:193

        // -- Contact us ----------------------------------------------

        router.post(
            '/contactUs',
            {
                subdomain: 'api',
                requireUserActor: true,
                allowFullAccessToken: true,
                rateLimit: {
                    scope: 'contact-us',
                    limit: 10,
                    window: 15 * 60_000,
                    key: 'user',
                },
            },
            async (req, res) => {
                const { message } = req.body ?? {};
                if (!message || typeof message !== 'string') {
                    throw new HttpError(400, '`message` is required', {
                        legacyCode: 'bad_request',
                    });
                }
                if (message.length > 100_000) {
                    throw new HttpError(
                        400,
                        '`message` is too long (max 100,000 characters)',
                        { legacyCode: 'bad_request' },
                    );
                }

                // Persist to feedback table for durability
                try {
                    await this.clients.db.write(
                        'INSERT INTO `feedback` (`user_id`, `message`) VALUES (?, ?)',
                        [req.actor.user.id, message],
                    );
                } catch (e) {

View on GitHub (pinned to 908ec23eda)

Solutions

  1. Send { message: '...' } as JSON with Content-Type: application/json.
  2. Ensure message is a non-empty string.
  3. Verify req.body is parsed (check Content-Type and that the body is not double-stringified).
  4. Confirm you are authenticated with a user actor or full-access token.

Example fix

// before
await fetch('/contactUs', { method:'POST', body: JSON.stringify({ text }) });
// after
await fetch('/contactUs', {
  method:'POST',
  headers:{'Content-Type':'application/json'},
  body: JSON.stringify({ message: text }),
});
Defensive patterns

Strategy: validation

Validate before calling

function buildContactBody(message) {
  if (typeof message !== 'string' || message.length === 0)
    throw new TypeError('message is required and must be a non-empty string');
  return { message };
}

Type guard

const isValidContactMessage = (m) => typeof m === 'string' && m.length > 0;

Try / catch

try { await post('/contactUs', { message }); }
catch (e) { if (e?.code === 'bad_request' && /message is required/.test(e.message)) alert('Please enter a message'); else throw e; }

Prevention

When it happens

Trigger: POSTing to /contactUs with no body, an empty message, a non-string message (number/object), or a Content-Type that fails to parse JSON so req.body is undefined.

Common situations: Missing or wrong Content-Type header (so body is undefined); form submission sending message in a different field; client sending {text} instead of {message}.

Related errors


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