toeverything/AFFiNE · error · QueryTooLong

query_too_long

query_too_long

Error message

Query is too long, max length is ${max}.

What it means

The admin shared-link listing in WorkspaceAnalyticsModel clamps pagination values but hard-rejects overlong keywords: after trimming, a keyword longer than DOC_MEMBER_QUERY_MAX_LENGTH (255 characters, workspace-analytics.ts:20) throws QueryTooLong with that max.

Solutions

  1. Enforce maxlength=255 plus trim on the client search input before calling the API.
  2. Validate keyword length in the calling service and reject or truncate with a friendly message.
  3. Split very long searches into several narrower queries.

Example fix

// before
const result = await analytics.adminListSharedLinks({ keyword: longDump }); // > 255 chars -> QueryTooLong

// after
const keyword = longDump.trim().slice(0, 255);
const result = await analytics.adminListSharedLinks({ keyword });
Defensive patterns

Strategy: validation

Validate before calling

const MAX = 255;
const keyword = rawKeyword.trim();
if (keyword.length > MAX) {
  throw new ValidationError(`Query is too long, max length is ${MAX}.`);
}
const page = await analytics.adminListSharedLinks({ keyword });

Try / catch

try { await analytics.adminListSharedLinks({ keyword }); } catch (e) { if (e instanceof QueryTooLong) trimAndRetry(); else throw e; }

Prevention

When it happens

Trigger: Calling the admin shared-links listing with options.keyword whose trimmed length exceeds 255 characters.

Common situations: Pasting a URL, stack trace, or a comma-separated list of emails into the search box; frontend search input without maxlength; e2e tests feeding synthetic long strings.

Related errors


AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18). Data as JSON: /api/errors/d5c87c155508706b. Report an issue: GitHub.

Appendix: source

Thrown at packages/backend/server/src/models/workspace-analytics.ts:572

      generatedAt: now,
    };
  }

  async adminPaginateAllSharedLinks(
    options: AdminAllSharedLinksOptions
  ): Promise<
    OptionalTotalPaginated<AdminSharedLinkNode> & {
      analyticsWindow: TimeWindowDto;
    }
  > {
    const pagination: PaginationInput = {
      ...options.pagination,
      first: Math.min(Math.max(options.pagination.first ?? 10, 1), 100),
      offset: Math.max(options.pagination.offset ?? 0, 0),
    };
    const keyword = options.keyword?.trim();
    if (keyword && keyword.length > DOC_MEMBER_QUERY_MAX_LENGTH) {
      throw new QueryTooLong({ max: DOC_MEMBER_QUERY_MAX_LENGTH });
    }

    const includeTotal = options.includeTotal ?? false;
    const orderBy = options.orderBy ?? 'UpdatedAtDesc';
    const analyticsWindowDays = clampInt(
      options.analyticsWindowDays,
      1,
      90,
      DEFAULT_ANALYTICS_WINDOW_DAYS
    );
    const now = new Date();
    const currentDay = startOfUtcDay(now);
    const analyticsFrom = addUtcDays(currentDay, -(analyticsWindowDays - 1));

    const cursor = parseJsonCursor<SharedLinkCursor>(pagination.after ?? null);
    const cursorCondition = this.buildSharedLinkCursorCondition(
      orderBy,
      cursor

View on GitHub (pinned to b4c8548c09)