{"record":{"id":"9e884fbd9dd21c70","repo":"actualbudget/actual","slug":"file-does-not-appear-to-be-a-valid-qif-file-lin","errorCode":null,"errorMessage":"File does not appear to be a valid qif file: ${line}","messagePattern":"File does not appear to be a valid qif file: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/loot-core/src/server/transactions/import/qif2json.ts","lineNumber":38,"sourceCode":"};\n\nexport function qif2json(qif, options: { dateFormat?: string } = {}) {\n  const lines = qif.split('\\n').filter(Boolean);\n  let line = lines.shift();\n  const type = /!Type:([^$]*)$/.exec(line.trim());\n  const data: {\n    dateFormat: string | undefined;\n    type?;\n    transactions: QIFTransaction[];\n  } = {\n    dateFormat: options.dateFormat,\n    transactions: [],\n  };\n  const transactions = data.transactions;\n  let transaction: QIFTransaction = {};\n\n  if (!type || !type.length) {\n    throw new Error('File does not appear to be a valid qif file: ' + line);\n  }\n  data.type = type[1];\n\n  let division: Division = {};\n\n  while ((line = lines.shift())) {\n    line = line.trim();\n    if (line === '^') {\n      transactions.push(transaction);\n      transaction = {};\n      continue;\n    }\n    switch (line[0]) {\n      case 'D':\n        transaction.date = line.substring(1);\n        break;\n      case 'T':\n        transaction.amount = line.substring(1);","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/loot-core/src/server/transactions/import/qif2json.ts#L20-L56","documentation":"qif2json requires the first line of a QIF file to be a type header of the form '!Type:Bank' (or similar). If the first line is empty or does not match the expected type pattern, the parser cannot determine the account type and throws this error including the offending line.","triggerScenarios":"Importing a file whose first line is blank, whose '!Type' header is misspelled (e.g. '!TYPE:Bank' with wrong capitalization is fine but '!Type' missing entirely is not), a file exported with a BOM or leading whitespace, or passing a non-QIF file (CSV, OFX) to parseQIF.","commonSituations":"Bank exports that prepend metadata lines before the !Type header; files saved with UTF-8 BOM by Windows tools; users renaming a CSV to .qif; truncated downloads missing the header.","solutions":["Open the file and verify the very first non-empty line starts with '!Type:' (e.g. '!Type:Bank').","Strip any UTF-8 BOM and leading blank lines before parsing.","Confirm the file is actually QIF format, not CSV/OFX renamed to .qif; re-export from the bank in QIF format.","Trim leading whitespace/newlines from the file content before passing it to parseQIF."],"exampleFix":"// before\nconst data = qif2json.parse(rawFileContents);\n// after\nconst cleaned = rawFileContents.replace(/^\\uFEFF/, '').replace(/^\\s+/, '');\nif (!/^!Type:/im.test(cleaned.split(/\\r?\\n/, 1)[0])) {\n  throw new Error('Missing !Type header — not a valid QIF file');\n}\nconst data = qif2json.parse(cleaned);","handlingStrategy":"validation","validationCode":"const firstLine = content.replace(/^\\uFEFF/, '').split(/\\r?\\n/, 1)[0];\nif (!/^!Type:/i.test(firstLine.trim())) {\n  throw new Error('Not a QIF file: missing !Type header on first line');\n}","typeGuard":"function isQifContent(content: string): boolean {\n  const first = content.replace(/^\\uFEFF/, '').trimStart().split(/\\r?\\n/, 1)[0];\n  return /^!Type:/i.test(first);\n}","tryCatchPattern":"try {\n  const data = parseQIF(file);\n} catch (e) {\n  if (e.message.startsWith('File does not appear to be a valid qif file')) {\n    showError('This file is not a valid QIF export. Check the first line is !Type:...');\n  } else { throw e; }\n}","preventionTips":["Strip BOM and leading whitespace before parsing","Verify the first line matches /^!Type:/i before importing","Confirm the file extension and content both indicate QIF, not CSV/OFX"],"tags":["import","qif","parsing","file-format"],"backgroundTag":"invalid-file-format","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}