calcom/cal.diy · warning · HttpError
Invalid request body
Error message
Invalid request body
What it means
Thrown when ZProjectMutationInputSchema.safeParse(req.body) fails - the body must be { projectId: string }. A missing projectId, a non-string value, or an empty body triggers it. Surfaced as HTTP 400.
Source
Thrown at packages/app-store/basecamp3/api/projectMutation.ts:28
import prisma from "@calcom/prisma";
import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential";
interface IDock {
id: number;
name: string;
}
const ZProjectMutationInputSchema = z.object({ projectId: z.string() });
async function handler(req: NextApiRequest) {
const userId = req.session?.user?.id;
if (!userId) {
throw new HttpError({ statusCode: 401, message: "Unauthorized" });
}
const parsed = ZProjectMutationInputSchema.safeParse(req.body ?? {});
if (!parsed.success) {
throw new HttpError({
statusCode: 400,
message: "Invalid request body",
});
}
const { projectId } = parsed.data;
const { user_agent } = await getAppKeysFromSlug("basecamp3");
const credential = await prisma.credential.findFirst({
where: { userId },
select: credentialForCalendarServiceSelect,
});
if (!credential) {
throw new HttpError({ statusCode: 403, message: "No credential found for user" });
}
let credentialKey = credential.key as BasecampToken;View on GitHub (pinned to 176037d0af)
Solutions
- Send { projectId: '123' } (string) as a JSON body.
- Validate on the client with the same Zod schema before posting.
- Ensure the request sets Content-Type: application/json.
Example fix
// before
fetch('/api/integrations/basecamp3/project', { method: 'POST', body: JSON.stringify({ projectId: 123 }) });
// after
fetch('/api/integrations/basecamp3/project', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ projectId: String(123) }),
}); Defensive patterns
Strategy: validation
Validate before calling
const parsed = ZProjectMutationInputSchema.safeParse(req.body ?? {});
if (!parsed.success) {
// surface parsed.error.issues to the client for a clearer message
} Type guard
const isProjectIdBody = (b: unknown): b is { projectId: string } =>
typeof b === 'object' && b !== null && typeof (b as any).projectId === 'string'; Prevention
- Validate the body with the same Zod schema on the client before posting.
- Always send projectId as a string with Content-Type: application/json.
- Reuse the exact field name 'projectId'.
When it happens
Trigger: POST with no body; projectId sent as a number instead of a string; wrong field name such as project_id; body sent as form-encoded instead of JSON.
Common situations: Frontend form bug omitting projectId; client serializing the field under a different key; missing Content-Type: application/json header.
Related errors
- parsedQuery.error.message
- Invalid refreshed tokens were returned
- Bad Request
- Cal.diy: Invalid BTCPay credentials
- Invalid credentials for userId ${credential.userId} and appI
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/bb08aa0e2e4d9ff2.
Report an issue: GitHub.