calcom/cal.diy · critical · Error

No app ticket found

Error message

No app ticket found

What it means

Thrown by getAppTicket in the Feishu calendar adapter when the app_ticket cannot be obtained. Feishu only delivers app_ticket via an event webhook (not a direct fetch); the handler triggers a resend and then pools the database (makePoolingPromise, 24 retries × 5s ≈ 2 minutes). If no ticket arrives within the window, it throws.

Source

Thrown at packages/app-store/feishucalendar/lib/AppAccessToken.ts:100

  /**
   * 1. App_ticket is only valid for 1 hr.
   * 2. The we cannot retrieve app_ticket by calling a API.
   * 3. App_ticket can only be retrieved in app_ticket event, which is push from feishu every hour.
   * 4. We can trigger feishu to push a new app_ticket
   * 5. Therefore, after trigger resend app_ticket ticket, we have to
   * pooling DB, as app_ticket will update ticket in DB
   * see
   * https://open.larksuite.com/document/ugTN1YjL4UTN24CO1UjN/uQjN1YjL0YTN24CN2UjN
   * https://open.larksuite.com/document/ukTMukTMukTM/ukDNz4SO0MjL5QzM/auth-v3/auth/app_ticket_resend
   */
  const appTicketNew = await makePoolingPromise(getAppTicketFromKeys);
  if (appTicketNew) {
    log.debug("has new app ticket", appTicketNew);
    return appTicketNew;
  }
  log.error("app ticket not found");
  throw new Error("No app ticket found");
};

export const getAppAccessToken: () => Promise<string> = async () => {
  log.debug("get app access token invoked");
  const appKeys = await getValidAppKeys();
  const appAccessToken = appKeys.app_access_token;
  const expireDate = appKeys.expire_date;

  if (appAccessToken && expireDate && !isExpired(expireDate)) {
    log.debug("get app access token not expired");
    return appAccessToken;
  }

  const appTicket = await getAppTicket();

  const fetchAppAccessToken = (app_ticket: string) =>
    fetch(`https://${FEISHU_HOST}/open-apis/auth/v3/app_access_token`, {
      method: "POST",

View on GitHub (pinned to 176037d0af)

Solutions

  1. Expose a public HTTPS URL for the Feishu webhook endpoint and register it in the Feishu developer console under event subscriptions.
  2. Enable the app_ticket event in the Feishu app's event configuration.
  3. Verify the Cal.com app's app_id / app_secret match the Feishu app so Feishu will push the ticket.
  4. Trigger the resend manually from the Feishu console to seed the DB, then retry.
  5. Increase the pooling window (times/delay in makePoolingPromise) if Feishu webhooks are slow.

Example fix

// before
const appTicketNew = await makePoolingPromise(getAppTicketFromKeys);
if (appTicketNew) return appTicketNew;
log.error("app ticket not found");
throw new Error("No app ticket found");

// after - extend window and surface cause
const appTicketNew = await makePoolingPromise(getAppTicketFromKeys, 60, 5_000);
if (!appTicketNew) {
  throw new Error("No Feishu app_ticket received within 5 minutes. Verify the app_ticket webhook is publicly reachable and the event is subscribed.");
}
return appTicketNew;
Defensive patterns

Strategy: retry

Validate before calling

const appKeys = await getAppKeys();
if (!appKeys?.app_id || !appKeys?.app_secret) throw new Error("Feishu app_id/app_secret not configured");
if (!appKeys?.open_verification_token) throw new Error("Feishu open_verification_token not configured");

Type guard

const hasFeishuAppKeys = (k: unknown): k is { app_id: string; app_secret: string } =>
  typeof k === "object" && k !== null &&
  typeof (k as any).app_id === "string" && typeof (k as any).app_secret === "string";

Try / catch

try {
  const token = await getAppAccessToken();
} catch (err) {
  if (err instanceof Error && /No app ticket found/i.test(err.message)) {
    // surface actionable guidance to ops
    throw new Error("Feishu app_ticket webhook unreachable. Register the app_ticket event subscription and expose a public callback URL.");
  }
  throw err;
}

Prevention

When it happens

Trigger: Feishu webhook endpoint for app_ticket events is not reachable (public URL not configured), the webhook was not registered for the Feishu app, the app's event subscription is disabled, or 2 minutes elapsed without Feishu pushing a new ticket.

Common situations: Self-hosted Cal.com without a public webhook URL; Feishu app's 'event subscription' missing the app_ticket event; Feishu app in review mode with webhooks disabled; network firewall blocking inbound Feishu webhook POST.

Related errors


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