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
- Send { message: '...' } as JSON with Content-Type: application/json.
- Ensure message is a non-empty string.
- Verify req.body is parsed (check Content-Type and that the body is not double-stringified).
- 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
- Always send Content-Type: application/json.
- Use the field name 'message'.
- Disable the submit button when the field is empty.
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.