{"record":{"id":"5a5ca3ea0bf754df","repo":"actualbudget/actual","slug":"user-id-is-required-for-file-creation","errorCode":null,"errorMessage":"User ID is required for file creation","messagePattern":"User ID is required for file creation","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/sync-server/src/app-sync.ts","lineNumber":384,"sourceCode":"    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');\n          })(),\n      }),\n    );\n\n    res.send({ status: 'ok', groupId });\n    return;\n  }\n\n  if (!groupId) {\n    // sync state was reset, create new group\n    const newGroupId = generateGroupId();\n    groupId = newGroupId;\n    filesService.update(fileId, new FileUpdate({ groupId: newGroupId }));\n  }\n\n  // Regardless, update some properties\n  filesService.update(\n    fileId,","sourceCodeStart":366,"sourceCodeEnd":402,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/sync-server/src/app-sync.ts#L366-L402","documentation":"Thrown inline in the file-creation handler (POST /files) of app-sync.ts when the authenticated request has no user_id on res.locals. The sync server requires every uploaded file to be owned by a known user, so if the auth middleware did not populate user_id, creation is aborted with this error instead of writing an orphaned file row.","triggerScenarios":"POST to the file-upload endpoint while res.locals.user_id is empty — i.e. the request reached the handler without going through (or failing silently in) the auth middleware, or the token validation step did not attach the user identity.","commonSituations":"Deployments where the auth middleware is misconfigured or omitted from the route stack; self-hosted setups with a reverse proxy that strips the Authorization header; custom clients calling the endpoint without a valid token; version mismatches after upgrading the sync server.","solutions":["Ensure the request carries a valid access token so the auth middleware sets res.locals.user_id.","Verify the auth middleware is registered before the file-creation route and matches the method (header vs openid).","If behind a proxy, confirm it forwards the Authorization header to the sync server.","Check server logs/auth config (ENABLE_OPENID, trusted proxies) to see why authentication was skipped."],"exampleFix":"// before\ncurl -X POST http://server/files -d '{...}'            // no token -> 500 'User ID is required...'\n// after\ncurl -X POST http://server/files -H \"Authorization: Bearer <token>\" -d '{...}'","handlingStrategy":"validation","validationCode":"// client-side, before POST /files\nif (!accessToken) throw new Error('Not authenticated: no access token for file upload');\nconst res = await fetch(base + '/files', { headers: { Authorization: `Bearer ${accessToken}` }, ... });\nif (res.status === 401 || res.status === 403) throw new Error('Auth middleware did not attach user identity');","typeGuard":"function hasUserId(locals: unknown): locals is { user_id: string } {\n  return typeof locals === 'object' && locals !== null && typeof (locals as any).user_id === 'string' && (locals as any).user_id.length > 0;\n}","tryCatchPattern":"try {\n  await createFile(payload);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('User ID is required')) {\n    await reauthenticate();\n    return createFile(payload);\n  }\n  throw err;\n}","preventionTips":["Always send a valid Authorization header on sync-server API calls.","Register auth middleware before all app-sync routes and add integration tests for unauthenticated requests.","Check proxy configs strip-headers settings for Authorization.","After upgrading the server, re-verify the auth flow end to end."],"tags":["auth","http","sync-server","missing-user-id"],"backgroundTag":"missing-authenticated-user-context","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}