actualbudget/actual · error · FileNotFound
File does not exist or you don't have access to it
Error message
File does not exist or you don't have access to it
What it means
FileNotFound is thrown by FilesService.get() when no row exists for the given fileId, or the row exists but is soft-deleted (deleted flag set). It is the canonical 'this file is not accessible to you' error of the app-sync files service.
Source
Thrown at packages/sync-server/src/app-sync/services/files-service.ts:142
encrypt_meta: string | null;
encrypt_salt: string | null;
encrypt_test: string | null;
encrypt_keyid: string | null;
deleted: number;
owner: string | null;
};
class FilesService {
accountDb: WrappedDatabase;
constructor(accountDb: WrappedDatabase) {
this.accountDb = accountDb;
}
get(fileId: FileId) {
const rawFile = this.getRaw(fileId);
if (!rawFile || (rawFile && rawFile.deleted)) {
throw new FileNotFound();
}
return this.validate(rawFile);
}
set(file: File) {
const deletedInt = boolToInt(file.deleted);
this.accountDb.mutate(
'INSERT INTO files (id, group_id, sync_version, name, encrypt_meta, encrypt_salt, encrypt_test, encrypt_keyid, deleted, owner) VALUES (?, ?, ?, ?, ?, ?, ?, ? ,?, ?)',
[
file.id,
file.groupId,
file.syncVersion?.toString(),
file.name,
file.encryptMeta,
file.encryptSalt,
file.encryptTest,
file.encryptKeyId,View on GitHub (pinned to d4334cb6e6)
Solutions
- Verify the file ID / sync ID used by the client exists in the files table of the account database.
- Confirm the client is talking to the correct sync server instance and uses the same user credentials.
- If the file was deleted, create/upload the file again or restore it from a backup.
- Clear stale local budget metadata and re-download or reset sync for that file.
Example fix
// before
await client.getFile('dead-file-id'); // FileNotFound
// after
const files = await client.listFiles();
const file = files.find(f => f.groupId === myGroupId);
await client.getFile(file.fileId); Defensive patterns
Strategy: try-catch
Validate before calling
// before fetching, confirm the id exists via list/find
const known = await client.listKnownFileIds?.() ?? [];
if (!known.includes(fileId)) console.warn(`File ${fileId} not in server list`); Type guard
function isFileNotFound(err: unknown): err is { type: 'file-not-found' } {
return typeof err === 'object' && err !== null && (err as any).type === 'file-not-found';
} Try / catch
try {
const file = filesService.get(fileId);
return file;
} catch (err) {
if (isFileNotFound(err)) {
return null; // treat as deleted / never existed; prompt user to re-create or reset sync
}
throw err;
} Prevention
- Refresh the client's file list after deletes on other devices.
- Point the client at the correct server URL and user credentials.
- Back up the account DB before resets to allow restoring deleted files.
- Treat 404-like file errors as a signal to re-download budget metadata instead of retrying blindly.
When it happens
Trigger: Any read path (verifyFileExists, sync handlers) calling get(fileId) with: an unknown ID, an ID belonging to another user after ownership validation, or a file that has been deleted (DELETE endpoint) but whose ID is still cached client-side.
Common situations: Client points at a different server/directory than where the budget was created; the budget file was deleted from another device; stale local metadata referencing an old group; database was reset or migrated.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- getServerErrorReason(json)
- User ID is required for file creation
- File not found
- File not found
- User or file not found
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/81035762f75a55c5.
Report an issue: GitHub.