actualbudget/actual · warning
fileId-required
fileId-required
Error message
fileId-required
What it means
POST /delete-user-file requires a fileId in the JSON body. When req.body is missing or has no truthy fileId, the server responds 422 with { details: 'fileId-required', reason: 'unprocessable-entity', status: 'error' }. This is a request-body validation error before any database or filesystem work.
Source
Thrown at packages/sync-server/src/app-sync.ts:548
data: {
deleted: boolToInt(file.deleted), // FIXME: convert to boolean, make sure it works in the frontend
fileId: file.id,
groupId: file.groupId,
name: file.name,
encryptMeta: file.encryptMeta ? JSON.parse(file.encryptMeta) : null,
usersWithAccess: fileService.findUsersWithAccess(file.id).map(access => ({
...access,
owner: access.userId === file.owner,
})),
},
});
});
app.post('/delete-user-file', (req, res) => {
const { fileId } = req.body || {};
if (!fileId) {
res.status(422).send({
details: 'fileId-required',
reason: 'unprocessable-entity',
status: 'error',
});
return;
}
const filesService = new FilesService(getAccountDb());
const file = verifyFileExists(fileId, filesService, res, 'file-not-found');
if (!file) {
return;
}
const fileAccessError = requireFileOwner(file, res.locals.user_id);
if (fileAccessError) {
res.status(403);
res.send(fileAccessError);
return;View on GitHub (pinned to d4334cb6e6)
Solutions
- Send a JSON body containing fileId: POST /delete-user-file with { "fileId": "<id>" }.
- Set Content-Type: application/json on the request so the express json parser populates req.body.
- Confirm the key name is exactly fileId (not id or fileId2).
Example fix
// before
await fetch(base + '/delete-user-file', { method: 'POST' });
// after
await fetch(base + '/delete-user-file', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ fileId }),
}); Defensive patterns
Strategy: validation
Validate before calling
if (!fileId || typeof fileId !== 'string') {
throw new Error('delete-user-file requires a non-empty fileId in the JSON body');
} Type guard
function hasFileId(body: unknown): body is { fileId: string } {
return typeof body === 'object' && body !== null &&
'fileId' in body && typeof (body as { fileId: unknown }).fileId === 'string' &&
(body as { fileId: string }).fileId.length > 0;
} Try / catch
const res = await fetch(base + '/delete-user-file', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ fileId }) });
if (res.status === 422) throw new Error('fileId-required: body must be JSON with fileId'); Prevention
- Always send JSON bodies with Content-Type: application/json.
- Use a typed API client so the fileId parameter is enforced at compile time.
- Double-check parameter naming matches the API (fileId, not id).
When it happens
Trigger: Calling /delete-user-file with an empty body, with Content-Type not set to application/json so req.body is {}, or with a body like {} / { fileId: null }.
Common situations: curl POSTs without -H 'Content-Type: application/json'; fetch calls omitting JSON.stringify of the payload; clients passing the file id under a wrong key (e.g. id instead of fileId).
Understand the failure class
Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.
Related errors
- Single file ID is required
- Invalid Origin header
- Invalid --name: must be a non-empty string.
- No update fields provided. Use --name or --offbudget.
- Invalid cutoff date: expected a valid date (e.g. YYYY-MM-DD)
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/65e0c9421f47a12a.
Report an issue: GitHub.