{"record":{"id":"fc841c321123aa2f","repo":"hcengineering/platform","slug":"result-error-fc841c","errorCode":null,"errorMessage":"result.error","messagePattern":"result\\.error","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"foundations/core/packages/collaborator-client/src/client.ts","lineNumber":91,"sourceCode":"    const url = concatLink(this.collaboratorUrl, `/rpc/${encodeURIComponent(documentId)}`)\n\n    const res = await fetch(url, {\n      method: 'POST',\n      headers: {\n        Authorization: 'Bearer ' + this.token,\n        'Content-Type': 'application/json'\n      },\n      body: JSON.stringify({ method, payload })\n    })\n\n    if (!res.ok) {\n      throw new Error('HTTP error ' + res.status)\n    }\n\n    const result = await res.json()\n\n    if (result.error != null) {\n      throw new Error(result.error)\n    }\n\n    return result as R\n  }\n\n  async getMarkup (document: CollaborativeDoc, source?: Ref<Blob> | null): Promise<Markup> {\n    const payload: GetContentRequest = {\n      source: source !== null ? source : undefined\n    }\n\n    const res = await retry(\n      3,\n      async () => {\n        return await this.rpc<GetContentRequest, GetContentResponse>(document, 'getContent', payload)\n      },\n      50\n    )\n","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/foundations/core/packages/collaborator-client/src/client.ts#L73-L109","documentation":"After a successful HTTP response, rpc checks the parsed JSON body for an application-level error field. If result.error is non-null, it is thrown as an Error. This means the HTTP call succeeded (2xx) but the collaborator operation itself failed.","triggerScenarios":"rpc() calls where the collaborator handler returns { error: ... } in the JSON body — e.g. document not found server-side, permission rejected at the application layer, or an internal handler exception serialized into the response.","commonSituations":"Markup operations on documents the collaborator doesn't know about; stale document IDs after re-creation; application-level permission rules differing from HTTP auth; collaborator internal bugs surfaced as error strings.","solutions":["Log result.error — it contains the collaborator's own error description.","Verify the document/collaborative doc exists and is registered with the collaborator service.","Check application-level permissions, not just HTTP auth.","Wrap rpc calls in try/catch and handle the error string (it is not a typed error).","If errors persist on valid input, check collaborator service logs/version for handler bugs."],"exampleFix":"// before\nconst markup = await client.getMarkup(doc)\n// after\ntry {\n  const markup = await client.getMarkup(doc)\n} catch (err) {\n  console.error('collaborator error:', err.message)\n  return defaultMarkup // fallback when doc not yet initialized\n}","handlingStrategy":"try-catch","validationCode":"// ensure doc is registered with the collaborator before rpc\nconst markup = await client.getMarkup(doc).catch(err =>\n  err.message.includes('not found') ? null : Promise.reject(err))\nif (markup === null) await client.updateMarkup(doc, initialMarkup)","typeGuard":"function hasPayloadError(result: { error?: unknown }): boolean {\n  return result.error != null\n}","tryCatchPattern":"try {\n  return await client.rpc(method, payload)\n} catch (err) {\n  // 2xx HTTP but application-level failure; err.message is the server's error string\n  console.error('collaborator rpc failed:', err.message)\n  return fallbackValue\n}","preventionTips":["Register/initialize collaborative docs before markup operations","Treat the thrown error string as application-level, not transport-level","Log the collaborator error string for server-side correlation","Provide defaults/fallbacks for optional markup data"],"tags":["rpc","collaborator","application-error"],"backgroundTag":"rpc-application-error","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}