{"record":{"id":"f8bcf7a3a9e65913","repo":"actualbudget/actual","slug":"error-f8bcf7","errorCode":"error","errorMessage":"error","messagePattern":"error","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"packages/sync-server/src/app-sync.ts","lineNumber":366,"sourceCode":"    ? requireFileAccess(currentFile, res.locals.user_id)\n    : null;\n  if (fileAccessError) {\n    res.status(403);\n    res.send(fileAccessError);\n    return;\n  }\n\n  const errorMessage = validateUploadedFile(groupId, keyId, currentFile);\n  if (errorMessage) {\n    res.status(400).send(errorMessage);\n    return;\n  }\n\n  try {\n    await fs.writeFile(getPathForUserFile(fileId), req.body);\n  } catch (err) {\n    console.log('Error writing file', err);\n    res.status(500).send({ status: 'error' });\n    return;\n  }\n\n  if (!currentFile) {\n    // it's new\n    const newGroupId = generateGroupId();\n    groupId = newGroupId;\n    filesService.set(\n      new File({\n        id: fileId,\n        groupId: newGroupId,\n        syncVersion: syncFormatVersion,\n        name,\n        encryptMeta,\n        owner:\n          res.locals.user_id ||\n          (() => {\n            throw new Error('User ID is required for file creation');","sourceCodeStart":348,"sourceCodeEnd":384,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/sync-server/src/app-sync.ts#L348-L384","documentation":"The POST /update-user-file endpoint failed while writing the uploaded budget file to disk (fs.writeFile inside a try/catch). The server logs 'Error writing file' with the underlying error and responds 500 with { status: 'error' } instead of storing the file and creating a new group id. This is a server-side filesystem failure, not a client payload problem.","triggerScenarios":"Uploading a user file via POST /update-user-file when fs.writeFile(getPathForUserFile(fileId), req.body) throws — e.g. the userFiles directory is missing, disk is full, or the process lacks write permission to the directory.","commonSituations":"Docker volume not mounted or mounted read-only so the userFiles dir doesn't exist; full disk on self-hosted instances; running the sync server as a user without permissions on the data directory; ENOSPC/ENOENT/EACCES errors.","solutions":["Verify the directory configured in userFiles exists and is writable by the sync-server process; create it and fix ownership/permissions (mkdir -p, chown).","Check free disk space on the volume backing userFiles (df -h) and free space if full.","Re-run the sync from the client after fixing storage; the client will re-upload the file.","Inspect server logs for the 'Error writing file' entry to see the exact errno (ENOENT/EACCES/ENOSPC) and address that cause."],"exampleFix":"// before (host): userFiles points at a path not created in the container\n// docker run -v data:/data actual-sync  # but USER_FILES=/app/user-files missing\n// after\n// docker run -v data:/app/user-files -e ACTUAL_USER_FILES=/app/user-files actual-sync\n// or create the dir before starting: mkdir -p \"$USER_FILES\"","handlingStrategy":"retry","validationCode":"// before upload, ensure storage exists\nimport fs from 'fs';\nif (!fs.existsSync(userFilesDir) || !fs.statSync(userFilesDir).isDirectory()) {\n  throw new Error('userFiles directory missing');\n}","typeGuard":null,"tryCatchPattern":"const res = await uploadFile(fileId, body);\nif (res.status === 500) {\n  // server-side write failure: fix storage, then retry\n  await ensureStorageAvailable();\n  await uploadFile(fileId, body);\n}","preventionTips":["Provision and chmod/chown the userFiles directory before starting the server.","Monitor disk space on the volume backing userFiles.","In containers, mount a persistent volume at the exact path userFiles points to.","Alert on the server-side 'Error writing file' log line."],"tags":["filesystem","server","io","upload"],"backgroundTag":"file-write-failed","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}