Skip to content

fix: parseJsonBody sends 500 for malformed JSON instead of 400 #4

Description

@iRonin

Problem

parseJsonBody() in worker/http.ts validates Content-Type but does not wrap request.json():

export function parseJsonBody<T = unknown>(request: Request): Promise<T> {
  const contentType = request.headers.get("content-type") || "";
  if (contentType && !contentType.toLowerCase().includes("application/json")) {
    throw new HttpError("Content-Type must be application/json", 415);
  }
  return request.json() as Promise<T>;
}

If the body contains malformed JSON, request.json() throws a raw SyntaxError. This bypasses HttpError handling and gets caught by the top-level try/catch in handleRequest, which renders it as a 500 internal_error instead of a 400 invalid_json.

Location

worker/http.tsparseJsonBody()

Proposed Fix

export async function parseJsonBody<T = unknown>(request: Request): Promise<T> {
  const contentType = request.headers.get("content-type") || "";
  if (contentType && !contentType.toLowerCase().includes("application/json")) {
    throw new HttpError("Content-Type must be application/json", 415);
  }
  try {
    return (await request.json()) as T;
  } catch {
    throw new HttpError("Invalid JSON in request body", 400, "invalid_request_error");
  }
}

Impact

  • Fixes incorrect HTTP status code for malformed JSON
  • Returns proper OpenAI-compatible error response
  • No API change for valid requests

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions