toeverything/AFFiNE · error · QueryTooLong

query_too_long

query_too_long

Error message

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

What it means

Thrown by the realtime workspace members search when input.query exceeds 255 characters — a hard input-size guard before the call to models.workspaceUser.search. Note the asymmetry: pagination.take is silently clamped (1..WORKSPACE_MEMBERS_REQUEST_TAKE_MAX) but an over-long query is rejected outright with QueryTooLong({ max: 255 }).

Solutions

  1. Trim and truncate the query to <=255 characters before sending
  2. Reject or sanitize paste-heavy input in the search UI
  3. Derive the limit from a shared constant if you control both sides

Example fix

// before
const members = await searchMembers({ workspaceId, query: rawInput });
// after
const query = rawInput.trim().slice(0, 255);
if (!query) return { members: [], memberCount: 0 };
const members = await searchMembers({ workspaceId, query });
Defensive patterns

Strategy: validation

Validate before calling

const MEMBERS_QUERY_MAX = 255;

export function sanitizeMemberQuery(raw: string): string | null {
  const q = raw.trim().slice(0, MEMBERS_QUERY_MAX);
  return q.length > 0 ? q : null; // null → skip the search call
}

const q = sanitizeMemberQuery(userInput);
if (q) {
  const res = await searchMembers({ workspaceId, query: q });
}

Type guard

function isQueryTooLong(e: unknown): e is { code: 'query_too_long'; max: number } {
  return typeof e === 'object' && e !== null && (e as any).code === 'query_too_long';
}

Try / catch

try {
  return await searchMembers({ workspaceId, query });
} catch (e) {
  if (isQueryTooLong(e)) {
    return searchMembers({ workspaceId, query: query.slice(0, e.max) }); // self-correct once
  }
  throw e;
}

Prevention

When it happens

Trigger: Realtime/GraphQL workspace members search invoked with query.length > 255 — pasted blobs of text, generated e2e strings, or filters concatenated programmatically into the query field.

Common situations: Search box receiving a huge paste; automated tests feeding unbounded strings; client filters built by joining many terms into one query.

Related errors


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

Appendix: source

Thrown at packages/backend/server/src/core/workspaces/realtime.ts:346

      workspaceId: string;
      skip?: number;
      take?: number;
      query?: string;
    }
  ) {
    await this.assertMembersRead(user.id, input.workspaceId);

    const pagination = {
      offset: Math.max(input.skip ?? 0, 0),
      first: Math.min(
        Math.max(input.take ?? 8, 1),
        WORKSPACE_MEMBERS_REQUEST_TAKE_MAX
      ),
    };

    if (input.query) {
      if (input.query.length > 255) {
        throw new QueryTooLong({ max: 255 });
      }
      const members = await this.models.workspaceUser.search(
        input.workspaceId,
        input.query,
        pagination
      );
      return {
        members: members.map(serializeWorkspaceMember),
        memberCount: await this.models.workspaceUser.count(input.workspaceId),
      };
    }

    const [members, memberCount] = await this.models.workspaceUser.paginate(
      input.workspaceId,
      pagination
    );
    return {
      members: members.map(serializeWorkspaceMember),

View on GitHub (pinned to 2af30773ae)