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
- Trim and truncate the query to <=255 characters before sending
- Reject or sanitize paste-heavy input in the search UI
- 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
- Enforce a max length on search inputs in the UI
- Truncate programmatically built queries before sending
- Keep the limit in one shared constant if you own both client and server
- In e2e tests, generate queries within the bound
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)