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

  1. Inspect the offending row: SELECT * FROM files WHERE id = ? and check the id format.
  2. Fix or delete the malformed row (or re-create the file through the normal upload flow).
  3. Never insert files rows manually — use FilesService.set().
  4. 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

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


AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29). Data as JSON: /api/errors/68e076579fb29567. Report an issue: GitHub.