{"record":{"id":"853598085106d785","repo":"hcengineering/platform","slug":"unknownerror-response-statustext","errorCode":null,"errorMessage":"unknownError(response.statusText)","messagePattern":"unknownError\\(response\\.statusText\\)","errorType":"exception","errorClass":"PlatformError","httpStatus":null,"severity":"error","filePath":"foundations/core/packages/api-client/src/rest/rest.ts","lineNumber":300,"sourceCode":"      params.append('query', query.query)\n      if (query.classes != null && Object.keys(query.classes).length > 0) {\n        params.append('classes', JSON.stringify(query.classes))\n      }\n      if (query.spaces != null && Object.keys(query.spaces).length > 0) {\n        params.append('spaces', JSON.stringify(query.spaces))\n      }\n      if (options.limit != null) {\n        params.append('limit', `${options.limit}`)\n      }\n      const requestUrl = concatLink(this.endpoint, `/api/v1/search-fulltext/${this.workspace}?${params.toString()}`)\n      const response = await fetch(requestUrl, {\n        method: 'GET',\n        headers: this.jsonHeaders(),\n        keepalive: true\n      })\n      if (!response.ok) {\n        await this.checkRateLimits(response)\n        throw new PlatformError(unknownError(response.statusText))\n      }\n      this.updateRateLimit(response)\n      return await extractJson<TxResult>(response)\n    })\n    if (result.error !== undefined) {\n      throw new PlatformError(result.error)\n    }\n    return result\n  }\n\n  async domainRequest<T>(\n    domain: OperationDomain,\n    params: DomainParams,\n    options?: DomainRequestOptions\n  ): Promise<DomainResult<T>> {\n    const requestUrl = concatLink(this.endpoint, `/api/v1/request/${domain}/${this.workspace}`)\n\n    await this.checkRate()","sourceCodeStart":282,"sourceCodeEnd":318,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/foundations/core/packages/api-client/src/rest/rest.ts#L282-L318","documentation":"In searchFulltext, if the HTTP response is not ok (and is not a 429 rate limit, which is handled first), the client throws a PlatformError built via unknownError(response.statusText). It represents an unexpected HTTP failure during a full-text search whose exact cause is only captured in the status/statusText.","triggerScenarios":"searchFulltext receiving a 4xx/5xx response (401 unauthorized token, 403 forbidden, 500 server error, 502/504 from a proxy) from the search endpoint.","commonSituations":"Expired or invalid token (401), missing permissions on the workspace (403), search/transactor service crash or restart (500), gateway timeouts under heavy load, server version mismatch altering the endpoint.","solutions":["Log response.statusText/status in a catch around searchFulltext and map 401 to re-authentication.","Refresh the token if the status is 401 and retry once.","Verify the workspace and query are valid and the user has access.","Retry with backoff for 5xx/502/504; check server health/logs for persistent 500s."],"exampleFix":"// before\nconst res = await client.searchFulltext(query, {})\n// after\nlet res\ntry { res = await client.searchFulltext(query, {}) }\ncatch (e) {\n  if (e instanceof PlatformError && /unauthorized/i.test(e.message)) { await reconnect(); res = await client.searchFulltext(query, {}) }\n  else throw e\n}","handlingStrategy":"try-catch","validationCode":"if (typeof query !== 'string' || query.trim() === '') throw new Error('searchFulltext requires a non-empty query')\n// also ensure the client was created with a valid, unexpired token","typeGuard":"function isPlatformError(e: unknown): e is PlatformError {\n  return e instanceof PlatformError\n}","tryCatchPattern":"try {\n  return await client.searchFulltext(query, {})\n} catch (e) {\n  if (isPlatformError(e)) {\n    if (/unauthorized|401/i.test(e.message)) { await refreshToken(); return client.searchFulltext(query, {}) }\n    if (/50[0234]/.test(e.message)) { await sleep(2000); return client.searchFulltext(query, {}) }\n  }\n  throw e\n}","preventionTips":["Refresh tokens proactively before expiry to avoid 401-driven failures","Retry idempotent searches with backoff on transient 5xx","Log statusText with context (query, workspace) for diagnosability","Keep client and server versions aligned"],"tags":["http","network","search"],"backgroundTag":"http-request-failed","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}