calcom/cal.diy · warning · BadRequestException

Invalid email ${trimmed}

Error message

Invalid email ${trimmed}

What it means

Thrown inside the GetManagedUsersInput DTO's @Transform on the `emails` field. When emails is provided as a comma-separated string, each value is split and trimmed; any token failing class-validator's isEmail check raises BadRequestException (HTTP 400) with the offending value interpolated. This validates the query param before the handler runs.

Source

Thrown at apps/api/v2/src/modules/oauth-clients/controllers/oauth-client-users/inputs/get-managed-users.input.ts:15

import { BadRequestException } from "@nestjs/common";
import { ApiPropertyOptional } from "@nestjs/swagger";
import { Transform } from "class-transformer";
import { ArrayNotEmpty, isEmail, IsOptional } from "class-validator";

import { Pagination } from "@calcom/platform-types";

export class GetManagedUsersInput extends Pagination {
  @IsOptional()
  @Transform(({ value }) => {
    if (typeof value === "string") {
      return value.split(",").map((email: string) => {
        const trimmed = email.trim();
        if (!isEmail(trimmed)) {
          throw new BadRequestException(`Invalid email ${trimmed}`);
        }
        return trimmed;
      });
    }
    return value;
  })
  @ArrayNotEmpty({ message: "emails cannot be empty." })
  @ApiPropertyOptional({
    description:
      "Filter managed users by email. If you want to filter by multiple emails, separate them with a comma.",
    example: "?emails=email1@example.com,email2@example.com",
  })
  emails?: string[];
}

View on GitHub (pinned to 176037d0af)

Solutions

  1. Sanitize the emails list client-side: trim, drop empties, validate with an email regex before sending.
  2. Use commas only as separators and ensure each token matches a standard email pattern.
  3. Send the request without the emails param if you want all managed users, since the field is @IsOptional.

Example fix

// before
?emails=foo,b ar@example.com

// after
const clean = raw.split(',').map(s=>s.trim()).filter(Boolean).filter(isEmailFormat);
?emails=foo@example.com,bar@example.com
Defensive patterns

Strategy: validation

Validate before calling

const emails = raw.split(',').map(s => s.trim()).filter(Boolean);
const invalid = emails.filter(e => !isEmail(e));
if (invalid.length) {
  throw new Error(`Invalid emails: ${invalid.join(', ')}`);
}
// then send ?emails=emails.join(',')

Type guard

const allValidEmails = (arr: string[]): boolean => arr.every(e => isEmail(e));

Prevention

When it happens

Trigger: GET request to the managed-users endpoint with ?emails= containing one or more malformed addresses, e.g. ?emails=foo, ?emails=a@b,c, ?emails=foo@bar@baz. The Transform throws during validation pipe processing.

Common situations: User types emails manually with typos; copy-paste includes trailing commas or spaces that yield empty tokens after split; mixed format like 'Name <a@b.com>' instead of bare address; trailing semicolon separators instead of commas.

Related errors


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