{"record":{"id":"f270b1a5f0f8b613","repo":"toeverything/AFFiNE","slug":"query-too-long","errorCode":"query_too_long","errorMessage":"Query is too long, max length is ${max}.","messagePattern":"Query is too long, max length is (.+?)\\.","errorType":"exception","errorClass":"QueryTooLong","httpStatus":400,"severity":"error","filePath":"packages/backend/server/src/core/workspaces/realtime.ts","lineNumber":346,"sourceCode":"      workspaceId: string;\n      skip?: number;\n      take?: number;\n      query?: string;\n    }\n  ) {\n    await this.assertMembersRead(user.id, input.workspaceId);\n\n    const pagination = {\n      offset: Math.max(input.skip ?? 0, 0),\n      first: Math.min(\n        Math.max(input.take ?? 8, 1),\n        WORKSPACE_MEMBERS_REQUEST_TAKE_MAX\n      ),\n    };\n\n    if (input.query) {\n      if (input.query.length > 255) {\n        throw new QueryTooLong({ max: 255 });\n      }\n      const members = await this.models.workspaceUser.search(\n        input.workspaceId,\n        input.query,\n        pagination\n      );\n      return {\n        members: members.map(serializeWorkspaceMember),\n        memberCount: await this.models.workspaceUser.count(input.workspaceId),\n      };\n    }\n\n    const [members, memberCount] = await this.models.workspaceUser.paginate(\n      input.workspaceId,\n      pagination\n    );\n    return {\n      members: members.map(serializeWorkspaceMember),","sourceCodeStart":328,"sourceCodeEnd":364,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/2af30773aecd567f09b346e7b72fc69143144057/packages/backend/server/src/core/workspaces/realtime.ts#L328-L364","documentation":"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 }).","triggerScenarios":"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.","commonSituations":"Search box receiving a huge paste; automated tests feeding unbounded strings; client filters built by joining many terms into one query.","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"],"exampleFix":"// before\nconst members = await searchMembers({ workspaceId, query: rawInput });\n// after\nconst query = rawInput.trim().slice(0, 255);\nif (!query) return { members: [], memberCount: 0 };\nconst members = await searchMembers({ workspaceId, query });","handlingStrategy":"validation","validationCode":"const MEMBERS_QUERY_MAX = 255;\n\nexport function sanitizeMemberQuery(raw: string): string | null {\n  const q = raw.trim().slice(0, MEMBERS_QUERY_MAX);\n  return q.length > 0 ? q : null; // null → skip the search call\n}\n\nconst q = sanitizeMemberQuery(userInput);\nif (q) {\n  const res = await searchMembers({ workspaceId, query: q });\n}","typeGuard":"function isQueryTooLong(e: unknown): e is { code: 'query_too_long'; max: number } {\n  return typeof e === 'object' && e !== null && (e as any).code === 'query_too_long';\n}","tryCatchPattern":"try {\n  return await searchMembers({ workspaceId, query });\n} catch (e) {\n  if (isQueryTooLong(e)) {\n    return searchMembers({ workspaceId, query: query.slice(0, e.max) }); // self-correct once\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["validation","search","input-length","realtime"],"backgroundTag":"input-length-limit-exceeded","analyzedSha":"2af30773aecd567f09b346e7b72fc69143144057","analyzedAt":"2026-08-18T21:16:52.546Z","contentChangedAt":"2026-08-18T21:16:52.546Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}