calcom/cal.diy · error · HttpError

Missing Giphy api_key

Error message

Missing Giphy api_key

What it means

Thrown by `checkGiphyApiKey` when the `api_key` field on the Giphy app's stored keys is not a string. Keys come from `getAppKeysFromSlug("giphy")`, which reads `app.keys` off the `App` row (returning `{}` when absent). If admins never configured a key, or stored it as a non-string JSON value, this fires as `HttpError` **400**. It guards every Giphy API call (`searchGiphy`, `getGiphyById`).

Source

Thrown at packages/app-store/giphy/lib/giphyManager.ts:8

import { HttpError } from "@calcom/lib/http-error";

import getAppKeysFromSlug from "../../_utils/getAppKeysFromSlug";

const checkGiphyApiKey = async () => {
  const appKeys = await getAppKeysFromSlug("giphy");
  if (typeof appKeys.api_key === "string") return appKeys.api_key;
  throw new HttpError({ statusCode: 400, message: "Missing Giphy api_key" });
};

export const searchGiphy = async (locale: string, keyword: string, offset = 0) => {
  const apiKey = await checkGiphyApiKey();
  const queryParams = new URLSearchParams({
    api_key: apiKey,
    q: keyword,
    limit: "1",
    offset: String(offset),
    // Contains images that are broadly accepted as appropriate and commonly witnessed by people in a public environment.
    rating: "g",
    lang: locale,
  });
  const response = await fetch(`https://api.giphy.com/v1/gifs/search?${queryParams.toString()}`, {
    method: "GET",
    headers: {
      Accept: "application/json",
    },

View on GitHub (pinned to 176037d0af)

Solutions

  1. In the admin app-store settings for Giphy, set `api_key` to a valid Giphy API key string and save, then verify the `App` row's `keys` JSON contains `"api_key": "<string>"`.
  2. Add a UI preflight: fetch the Giphy app keys and disable/hide the GIF picker when `api_key` is missing so users never reach the 400.
  3. Tighten the guard to also reject blank strings (`!key.trim()`) so a whitespace-only value is treated as missing.

Example fix

// before
const checkGiphyApiKey = async () => {
  const appKeys = await getAppKeysFromSlug("giphy");
  if (typeof appKeys.api_key === "string") return appKeys.api_key;
  throw new HttpError({ statusCode: 400, message: "Missing Giphy api_key" });
};
// after
const checkGiphyApiKey = async () => {
  const appKeys = await getAppKeysFromSlug("giphy");
  const key = typeof appKeys.api_key === "string" ? appKeys.api_key.trim() : "";
  if (key) return appKeys.api_key as string;
  throw new HttpError({ statusCode: 400, message: "Missing Giphy api_key" });
};
Defensive patterns

Strategy: validation

Validate before calling

// Check the configured key before invoking any Giphy manager function
import getAppKeysFromSlug from "@calcom/app-store/_utils/getAppKeysFromSlug";

async function getGiphyApiKeyOrNull() {
  const keys = await getAppKeysFromSlug("giphy");
  return typeof keys.api_key === "string" && keys.api_key.trim() ? (keys.api_key as string) : null;
}

// usage: skip the GIF picker when null
const apiKey = await getGiphyApiKeyOrNull();
if (!apiKey) { /* hide/disable GIF picker, do not call searchGiphy */ }

Type guard

function hasGiphyApiKey(keys: Record<string, unknown>): keys is { api_key: string } {
  return typeof keys.api_key === "string" && (keys.api_key as string).trim().length > 0;
}

Prevention

When it happens

Trigger: Calling `searchGiphy(locale, keyword, offset)` or `getGiphyById(giphyId)` — i.e. the GIF picker in the event/booking UI — when the Giphy app's `api_key` is unset, empty (but non-string-typed), or stored as an object/number in the app-store admin settings (`App.keys` JSON).

Common situations: Fresh deployment where the admin never entered a Giphy key; key was put in an env var instead of the app-store settings UI; `App` row seeded without keys; key saved as a JSON object `{ api_key: { ... } }` by mistake.

Related errors


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