calcom/cal.diy · warning · HttpError

Bad Request (Invalid JSON)

Error message

Bad Request (Invalid JSON)

What it means

Thrown by parseRequestData (HttpError, HTTP 400) when req.json() throws for an application/json request — the body is not valid JSON. A log.error records the parse exception and path. This is the JSON branch of the content-type dispatcher.

Source

Thrown at apps/web/app/api/parseRequestData.ts:37

export async function parseMultiFormData(req: NextRequest): Promise<Record<string, any>> {
  try {
    const formData = await req.formData();
    return Object.fromEntries(formData.entries());
  } catch (e) {
    log.error(`Invalid Multi Form Data: ${e} from path ${req.nextUrl}`);
    throw new HttpError({ statusCode: 400, message: "Bad Request (Invalid Multi Form Data)" });
  }
}

export async function parseRequestData(req: NextRequest): Promise<Record<string, any>> {
  const contentType = req.headers.get("content-type") ?? "application/json";
  if (contentType.includes("application/json")) {
    try {
      return await req.json();
    } catch (e) {
      log.error(`Invalid JSON: ${e} from path ${req.nextUrl}`);
      throw new HttpError({ statusCode: 400, message: "Bad Request (Invalid JSON)" });
    }
  }

  if (contentType.includes("application/x-www-form-urlencoded")) {
    return await parseUrlFormData(req);
  }

  if (contentType.includes("multipart/form-data")) {
    return await parseMultiFormData(req);
  }

  log.error(`Unsupported content type: ${contentType} from path ${req.nextUrl}`);
  throw new HttpError({ statusCode: 415, message: `Unsupported Content-Type. Expected ${contentType}` });
}

View on GitHub (pinned to 176037d0af)

Solutions

  1. Always JSON.stringify objects before sending as application/json.
  2. Validate JSON.parse in a try/catch on the client before submit to surface the exact syntax error.
  3. Ensure proxies/middleware do not alter or truncate the body, and that Content-Type matches the actual payload.
  4. Inspect the logged underlying error for the JSON parse position.

Example fix

// before
await fetch('/api/x', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: '{ name: "a", }', // invalid JSON
});

// after
const payload = JSON.stringify({ name: 'a' });
JSON.parse(payload); // sanity check client-side
await fetch('/api/x', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: payload,
});
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate JSON client-side before sending
const body = JSON.stringify(payload);
JSON.parse(body); // throws here if payload is not serializable cleanly
await fetch('/api/x', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body,
});

Type guard

function isParsableJson(s: string): boolean {
  try { JSON.parse(s); return true; } catch { return false; }
}

Try / catch

try {
  return await req.json();
} catch (e) {
  throw new HttpError({ statusCode: 400, message: 'Bad Request (Invalid JSON)' });
}

Prevention

When it happens

Trigger: POST with Content-Type application/json whose body is malformed JSON: trailing commas, single quotes, unquoted keys, truncated payload, or HTML/text returned through a proxy that rewrites content-type.

Common situations: Hand-built fetch with a non-JSON string body, JSON.stringify omitted, body cut off by a size limit, double JSON encoding, BOM/control characters in the payload.

Understand the failure class

Related errors


AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12). Data as JSON: /api/errors/6c644c18b6c17f75. Report an issue: GitHub.