ComposioHQ/composio · error · ValidationError

A non-empty userId is required to create a trigger

Error message

A non-empty userId is required to create a trigger

What it means

ValidationError('A non-empty userId is required to create a trigger') is thrown by Triggers.create when userId is undefined, null, or whitespace-only (checked via !userId?.trim()). Trigger instances are scoped per user, so this guard fires first — before body schema validation and any network call. Note it carries no cause.

Source

Thrown at ts/packages/core/src/models/Triggers.ts:332

  }

  /**
   * Create a new trigger instance for a user
   * If the connected account id is not provided, the first connected account for the user and toolkit will be used
   *
   * @param {string} userId - The user id of the trigger instance
   * @param {string} slug - The slug of the trigger instance
   * @param {TriggerInstanceUpsertParams} body - The parameters to create the trigger instance
   * @returns {Promise<TriggerInstanceUpsertResponse>} The created trigger instance
   */
  async create(
    userId: string,
    slug: string,
    body?: TriggerInstanceUpsertParams,
    requestOptions?: ComposioRequestOptions
  ): Promise<TriggerInstanceUpsertResponse> {
    if (!userId?.trim()) {
      throw new ValidationError(`A non-empty userId is required to create a trigger`);
    }

    const parsedBody = TriggerInstanceUpsertParamsSchema.safeParse(body ?? {});

    if (!parsedBody.success) {
      throw new ValidationError(`Invalid parameters passed to create trigger`, {
        cause: parsedBody.error,
      });
    }

    // Validate the trigger slug up-front so callers get a clear client-side
    // `ComposioTriggerTypeNotFoundError`. The Python SDK mirrors this behavior.
    try {
      await this.getType(slug, requestOptions);
    } catch (error) {
      // The trigger types endpoint returns 400 (not 404) for an unknown slug.
      if (error instanceof APIError && (error.status === 400 || error.status === 404)) {
        throw new ComposioTriggerTypeNotFoundError(`Trigger type ${slug} not found`, {

View on GitHub (pinned to 64b1b85502)

Solutions

  1. Pass a real non-empty user identifier as the first argument
  2. Verify argument order: create(userId, slug, body)
  3. Assert a non-empty user id upstream (e.g. from the auth session) before creating triggers

Example fix

// before
await triggers.create('', 'github_issue_opened', { triggerConfig: {...} });

// after
await triggers.create('user_12345', 'github_issue_opened', { triggerConfig: {...} });
Defensive patterns

Strategy: type-guard

Validate before calling

const userId = session.user?.id ?? '';
if (!userId.trim()) throw new Error('Cannot create trigger: no authenticated user');
await triggers.create(userId, slug, body);

Type guard

const isNonEmptyUserId = (id: unknown): id is string =>
  typeof id === 'string' && id.trim().length > 0;

Try / catch

try {
  await triggers.create(userId, slug, body);
} catch (e) {
  if (e instanceof ValidationError && /non-empty userId/.test(e.message)) {
    // re-authenticate or skip trigger creation for anonymous users
  }
}

Prevention

When it happens

Trigger: Calling triggers.create(userId, slug, body) with userId that is undefined, '', or ' '.

Common situations: Wrong argument order (passing slug first); userId loaded from an unset session/env variable; refactors renaming the user-id variable leaving undefined; background jobs where the user context was lost.

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


AI-assisted analysis of ComposioHQ/composio@64b1b85502 (2026-08-28). Data as JSON: /api/errors/9f6292db70f5d7ac. Report an issue: GitHub.