actualbudget/actual · error · GenericFileError
Invalid file ID
Error message
Invalid file ID
What it means
GenericFileError thrown by FilesService.validate() when the raw file row's id fails isValidFileId(). validate() runs on every get/find/update return path, so a stored row whose id is not a structurally valid FileId (expected format, e.g. UUID) breaks all reads of that file.
Source
Thrown at packages/sync-server/src/app-sync/services/files-service.ts:275
}
}
// Return the modified object
const rawFile = this.getRaw(id);
if (!rawFile) {
throw new GenericFileError('File not found', { id });
}
return this.validate(rawFile);
}
getRaw(fileId: FileId): RawFile | null {
return this.accountDb.first(`SELECT * FROM files WHERE id = ?`, [fileId]);
}
validate(rawFile: RawFile) {
const fileId = rawFile.id;
if (!isValidFileId(fileId)) {
throw new GenericFileError('Invalid file ID', { fileId });
}
let groupId: GroupId | null = null;
if (rawFile.group_id !== null) {
if (!isValidGroupId(rawFile.group_id)) {
throw new GenericFileError('Invalid group ID', {
groupId: rawFile.group_id,
});
}
groupId = rawFile.group_id;
}
return new File({
id: fileId,
name: rawFile.name,
groupId,
encryptSalt: rawFile.encrypt_salt,
encryptTest: rawFile.encrypt_test,View on GitHub (pinned to d4334cb6e6)
Solutions
- Inspect the offending row: SELECT * FROM files WHERE id = ? and check the id format.
- Fix or delete the malformed row (or re-create the file through the normal upload flow).
- Never insert files rows manually — use FilesService.set().
- Re-run any needed migrations so IDs conform to the current FileId format.
Example fix
// before
INSERT INTO files (id, ...) VALUES ('my-budget', ...); // invalid id -> 'Invalid file ID'
// after
const id = uuid.v4();
INSERT INTO files (id, ...) VALUES (?, ...); // valid FileId Defensive patterns
Strategy: validation
Validate before calling
import { isValidFileId } from './utils';
const raw = filesService.getRaw(id);
if (!raw || !isValidFileId(raw.id)) throw new Error(`File ${id} is corrupt or missing`); Type guard
function hasValidFileId(raw: { id: string } | null): raw is { id: string } {
return raw !== null && isValidFileId(raw.id);
} Try / catch
try {
return filesService.get(fileId);
} catch (err) {
if (err instanceof Error && err.message === 'Invalid file ID') {
// corrupt row: quarantine and prompt re-creation of the file
return null;
}
throw err;
} Prevention
- Never insert rows into the files table manually; use FilesService.set().
- Generate IDs with the same uuid library/version the server uses.
- Validate fixtures and backups before restoring them into the account DB.
- Add a startup sanity check that validates all file rows.
When it happens
Trigger: Directly inserted or manually edited rows in the files table with a malformed id; migration/test fixtures with fabricated IDs; older schema rows migrated into a newer server that enforces ID format.
Common situations: Hand-seeded dev databases; importing rows from backups of different Actual versions; scripts writing to files table without using the service API.
Related errors
- Invalid group ID
- Category '${category.name}' already exists in group '${categ
- An '${existingGroup.name}' account group already exists.
- ${name} is missing field ${String(field)}
- Could not update File
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/68e076579fb29567.
Report an issue: GitHub.