{"record":{"id":"0a68b1d37d7298e2","repo":"actualbudget/actual","slug":"invalid-meta-file","errorCode":"invalid-meta-file","errorMessage":"invalid-meta-file","messagePattern":"invalid-meta-file","errorType":"error_code","errorClass":"FileDownloadError","httpStatus":null,"severity":"error","filePath":"packages/loot-core/src/server/cloud-storage.ts","lineNumber":253,"sourceCode":"    : sharedDirs.length === 1\n      ? sharedDirs[0]\n      : null;\n\n  if (dir == null) {\n    throw FileDownloadError('invalid-zip-file');\n  }\n\n  const entryName = dir + 'db.sqlite';\n  const metaEntryName = dir + 'metadata.json';\n\n  const dbContent = Buffer.from(entries[entryName]);\n  const metaContent = Buffer.from(entries[metaEntryName]);\n\n  let meta;\n  try {\n    meta = JSON.parse(metaContent.toString('utf8'));\n  } catch {\n    throw FileDownloadError('invalid-meta-file');\n  }\n\n  // Update the metadata. The stored file on the server might be\n  // out-of-date with a few keys\n  meta = {\n    ...meta,\n    cloudFileId: fileData.fileId,\n    groupId: fileData.groupId,\n    lastUploaded: monthUtils.currentDay(),\n    encryptKeyId: fileData.encryptMeta ? fileData.encryptMeta.keyId : null,\n  };\n\n  const budgetDir = fs.getBudgetDir(meta.id);\n\n  if (await fs.exists(budgetDir)) {\n    // Don't remove the directory so that backups are retained\n    const dbFile = fs.join(budgetDir, 'db.sqlite');\n    const metaFile = fs.join(budgetDir, 'metadata.json');","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/loot-core/src/server/cloud-storage.ts#L235-L271","documentation":"FileDownloadError('invalid-meta-file') is thrown by importBuffer when metadata.json inside the downloaded archive cannot be parsed as JSON. The db.sqlite file was found, but the accompanying metadata (budget id, name, cloud ids) is corrupt, so the budget cannot be registered locally.","triggerScenarios":"calling download() or importActual() with an archive whose metadata.json entry is empty, truncated, or contains invalid JSON.","commonSituations":"a partially uploaded/corrupted cloud file, archives edited by hand where metadata.json was mangled, disk corruption on the sync server, or encoding damage from binary-mode text edits.","solutions":["Re-download the file from the server; the local copy may be corrupted in transit","Restore the budget from a local backup (files/backups directory) and re-upload it","If the metadata is recoverable, fix metadata.json to be valid JSON with at least an \"id\" field, then re-zip","Check sync-server logs/storage for corruption and re-upload a known-good export"],"exampleFix":"// before: trusting archive metadata\nawait importActual(buffer);\n// after: pre-validate metadata JSON\nconst meta = JSON.parse(zip.entries['metadata.json'].toString('utf8')); // throws early with clearer error\nif (!meta.id) throw new Error('metadata.json missing id');","handlingStrategy":"validation","validationCode":"function validateArchiveMeta(entries) {\n  const entry = Object.keys(entries).find(n => n === 'metadata.json' || n.endsWith('/metadata.json'));\n  if (!entry) throw new Error('metadata.json missing');\n  const meta = JSON.parse(Buffer.from(entries[entry]).toString('utf8'));\n  if (typeof meta.id !== 'string' || !meta.id) throw new Error('metadata.json has no id');\n  return meta;\n}","typeGuard":"function isValidBudgetMeta(v) {\n  return typeof v === 'object' && v !== null && typeof v.id === 'string' && v.id.length > 0;\n}","tryCatchPattern":"try {\n  await importActual(buffer);\n} catch (e) {\n  if (e instanceof FileDownloadError && e.reason === 'invalid-meta-file') {\n    console.error('metadata.json is corrupt; restore from backup or re-download.');\n  } else throw e;\n}","preventionTips":["Do not edit metadata.json inside archives; if you must, validate JSON afterwards","Verify cloud files periodically by downloading and parsing metadata","Keep local backups in files/ so a corrupt cloud copy is recoverable","Use binary-safe tools when handling zips (no text-mode conversions)"],"tags":["json","file-import","data-integrity","cloud-sync"],"backgroundTag":"invalid-json","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}