{"record":{"id":"7585827a24184579","repo":"actualbudget/actual","slug":"responsedata-description-responsedata-reason","errorCode":null,"errorMessage":"responseData.description || responseData.reason || 'unknown'","messagePattern":"responseData\\.description \\|\\| responseData\\.reason \\|\\| 'unknown'","errorType":"error_code","errorClass":"PostError","httpStatus":null,"severity":"error","filePath":"packages/loot-core/src/server/post.ts","lineNumber":115,"sourceCode":"\n  try {\n    responseData = JSON.parse(text);\n  } catch {\n    // Something seriously went wrong. TODO handle errors\n    throw new PostError('parse-json', { meta: text });\n  }\n\n  if (responseData.status !== 'ok') {\n    logger.log(\n      'API call failed: ' +\n        url +\n        '\\nData: ' +\n        JSON.stringify(data, null, 2) +\n        '\\nResponse: ' +\n        JSON.stringify(res, null, 2),\n    );\n\n    throw new PostError(\n      responseData.description || responseData.reason || 'unknown',\n    );\n  }\n\n  return responseData.data;\n}\n\nexport async function del(url, data, headers = {}, timeout = null) {\n  let text;\n  let res;\n\n  try {\n    const controller = new AbortController();\n    const timeoutId = setTimeout(() => controller.abort(), timeout);\n    const signal = timeout ? controller.signal : null;\n    res = await fetch(url, {\n      method: 'DELETE',\n      body: JSON.stringify(data),","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/loot-core/src/server/post.ts#L97-L133","documentation":"When the sync server returns HTTP 200 but the JSON payload has status !== 'ok', `post` throws a PostError whose message is the server-provided `description` or `reason` (falling back to 'unknown'). This is an application-level failure reported by the server itself; the full request data and response are logged for diagnosis.","triggerScenarios":"checkKey, resetSyncState, removeFile, or update-user-filename calls (post) where the server responds {status: <not 'ok'>, description/reason: ...} — e.g. invalid user token, unknown fileId, or server-side validation rejecting the request.","commonSituations":"Expired or missing user-token after server restart or logout; budget name update targeting a cloudFileId the server doesn't recognize ('file-not-found'); mismatched server version that rejects a request field; 'unknown' when the server sends a non-ok status with neither description nor reason.","solutions":["Read the thrown PostError message (description/reason) and the logged 'API call failed' output to identify the server-side reason.","If the reason is token-related (e.g. token-expired), sign in again to obtain a fresh user-token.","Verify the fileId/cloudFileId used in the request exists on the server.","If the message is 'unknown', check sync server logs for the corresponding request to find the underlying error.","Upgrade both client and sync server to compatible versions."],"exampleFix":"// before: stale token kept after server was reset\nawait post(server + '/update-user-filename', { token: oldToken, ... });\n// after: re-login first\nconst token = await signInAndGetToken(password); // fresh user-token\nawait post(server + '/update-user-filename', { token, ... });","handlingStrategy":"try-catch","validationCode":"const token = await asyncStorage.getItem('user-token');\nif (!token) throw new Error('Not signed in: no user-token available for server call');","typeGuard":"function isServerRejection(e: unknown): e is { reason: string; details?: unknown } {\n  return typeof e === 'object' && e !== null && 'reason' in e && typeof (e as any).reason === 'string' && (e as any).reason !== 'ok';\n}","tryCatchPattern":"try {\n  await post(server + '/update-user-filename', { token, fileId, name });\n} catch (e) {\n  if (isPostError(e) && /token|unauthorized/i.test(e.message)) {\n    await reauthenticate(); // get a fresh user-token and retry once\n  } else {\n    throw e;\n  }\n}","preventionTips":["Re-authenticate whenever a token-expired reason is returned instead of reusing stale tokens.","Verify fileIds exist on the server before update/delete operations.","Keep client and sync server versions aligned.","Check server logs whenever the error message is 'unknown'."],"tags":["sync-server","api-response","authentication","server-error"],"backgroundTag":"server-rejected-request","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}