calcom/cal.diy · error · BadRequestException

Could not create UTC time for slot ${slot.time}

Error message

Could not create UTC time for slot ${slot.time}

What it means

A NestJS BadRequestException (HTTP 400) from SlotsOutputService_2024_09_04.getAvailableRangeSlots — the no-timeZone branch. The slot.time itself could not be converted to ISO even in UTC: DateTime.fromISO(slot.time,{zone:'utc'}).toISO() returned null. This is a data-integrity signal: the upstream availableSlots service produced a slot whose time is not a valid ISO string.

Source

Thrown at apps/api/v2/src/modules/slots/slots-2024-09-04/services/slots-output.service.ts:156

              );
            }

            if (!eventType?.seatsPerTimeSlot) {
              return this.getAvailableRangeSlot(start, end);
            }
            return this.getAvailableRangeSlotSeated(
              start,
              end,
              slot.attendees || 0,
              eventType.seatsPerTimeSlot ?? undefined,
              slot.bookingUid
            );
          } else {
            const start = DateTime.fromISO(slot.time, { zone: "utc" }).toISO();
            const end = DateTime.fromISO(slot.time, { zone: "utc" }).plus({ minutes: slotDuration }).toISO();

            if (!start || !end) {
              throw new BadRequestException(`Could not create UTC time for slot ${slot.time}`);
            }

            if (!eventType?.seatsPerTimeSlot) {
              return this.getAvailableRangeSlot(start, end);
            }
            return this.getAvailableRangeSlotSeated(
              start,
              end,
              slot.attendees || 0,
              eventType.seatsPerTimeSlot ?? undefined,
              slot.bookingUid
            );
          }
        });
      }
      return acc;
    }, {});

View on GitHub (pinned to 176037d0af)

Solutions

  1. Retry the request once — transient bad slots can clear on availability recompute.
  2. Narrow the query window (start/end) to isolate which date produces the bad slot and report it.
  3. Switch format to 'time' (default) instead of 'range' to bypass the range-specific UTC conversion path.
  4. File a server-side bug: AvailableSlotsService should never emit a slot whose time fails DateTime.fromISO.

Example fix

// before
fetch(`/v2/slots?format=range&...`)

// after — fall back to default time format, or shrink the window
fetch(`/v2/slots?format=time&...`)
// then report the bad date range to the platform team
Defensive patterns

Strategy: retry

Validate before calling

// This error reflects bad SERVER-side slot data, not caller input.
// Mitigation: shrink the window so the request avoids the corrupt slot.
function safeWindow(startISO: string, endISO: string) {
  const start = DateTime.fromISO(startISO, { zone: 'utc' });
  const end = DateTime.fromISO(endISO, { zone: 'utc' });
  if (!start.isValid || !end.isValid) throw new RangeError('bad window');
  // keep windows short to reduce chance of hitting a corrupt slot
  const span = end.diff(start, 'days').days;
  if (span > 7) throw new RangeError('narrow the window to <= 7 days for range format');
}

Try / catch

try {
  return await cal.slots.list({ format: 'range', ... });
} catch (e) {
  if (e instanceof HttpError && e.statusCode === 400 && /Could not create UTC time/i.test(e.message)) {
    // retry once with default time format, then report
    return cal.slots.list({ format: 'time', ... });
  }
  throw e;
}

Prevention

When it happens

Trigger: GET /v2/slots with format=range and no timeZone, where the availability engine returned a malformed slot.time (e.g. an empty string, a date-only value, or a corrupt entry). The client request is fine; the server's slot data is bad.

Common situations: A bug or override in AvailableSlotsService producing non-ISO times; a database row with a null/empty startTime surfacing as an empty string; a custom event type whose schedule produces an edge-case slot luxon cannot render.

Related errors


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