{"record":{"id":"68e076579fb29567","repo":"actualbudget/actual","slug":"invalid-file-id","errorCode":null,"errorMessage":"Invalid file ID","messagePattern":"Invalid file ID","errorType":"exception","errorClass":"GenericFileError","httpStatus":null,"severity":"error","filePath":"packages/sync-server/src/app-sync/services/files-service.ts","lineNumber":275,"sourceCode":"      }\n    }\n\n    // Return the modified object\n    const rawFile = this.getRaw(id);\n    if (!rawFile) {\n      throw new GenericFileError('File not found', { id });\n    }\n    return this.validate(rawFile);\n  }\n\n  getRaw(fileId: FileId): RawFile | null {\n    return this.accountDb.first(`SELECT * FROM files WHERE id = ?`, [fileId]);\n  }\n\n  validate(rawFile: RawFile) {\n    const fileId = rawFile.id;\n    if (!isValidFileId(fileId)) {\n      throw new GenericFileError('Invalid file ID', { fileId });\n    }\n\n    let groupId: GroupId | null = null;\n    if (rawFile.group_id !== null) {\n      if (!isValidGroupId(rawFile.group_id)) {\n        throw new GenericFileError('Invalid group ID', {\n          groupId: rawFile.group_id,\n        });\n      }\n      groupId = rawFile.group_id;\n    }\n\n    return new File({\n      id: fileId,\n      name: rawFile.name,\n      groupId,\n      encryptSalt: rawFile.encrypt_salt,\n      encryptTest: rawFile.encrypt_test,","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/sync-server/src/app-sync/services/files-service.ts#L257-L293","documentation":"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.","triggerScenarios":"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.","commonSituations":"Hand-seeded dev databases; importing rows from backups of different Actual versions; scripts writing to files table without using the service API.","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."],"exampleFix":"// before\nINSERT INTO files (id, ...) VALUES ('my-budget', ...);   // invalid id -> 'Invalid file ID'\n// after\nconst id = uuid.v4();\nINSERT INTO files (id, ...) VALUES (?, ...);              // valid FileId","handlingStrategy":"validation","validationCode":"import { isValidFileId } from './utils';\nconst raw = filesService.getRaw(id);\nif (!raw || !isValidFileId(raw.id)) throw new Error(`File ${id} is corrupt or missing`);","typeGuard":"function hasValidFileId(raw: { id: string } | null): raw is { id: string } {\n  return raw !== null && isValidFileId(raw.id);\n}","tryCatchPattern":"try {\n  return filesService.get(fileId);\n} catch (err) {\n  if (err instanceof Error && err.message === 'Invalid file ID') {\n    // corrupt row: quarantine and prompt re-creation of the file\n    return null;\n  }\n  throw err;\n}","preventionTips":["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."],"tags":["validation","corrupt-data","sync-server","database"],"backgroundTag":"invalid-identifier-format","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}