{"record":{"id":"2d3f0ff5f5ddbdad","repo":"actualbudget/actual","slug":"report-name-is-required","errorCode":null,"errorMessage":"Report name is required","messagePattern":"Report name is required","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/loot-core/src/server/reports/app.ts","lineNumber":141,"sourceCode":"    then no name change was made.\n    -if they are not the same then there is another\n    item with that name already.\n    */\n    return idForName.id !== reportId;\n  }\n\n  //default return: item was found but does not match current name\n  return true;\n}\n\nasync function createReport(report: CustomReportEntity) {\n  const reportId = uuidv4();\n  const item: CustomReportEntity = {\n    ...report,\n    id: reportId,\n  };\n  if (!item.name) {\n    throw new Error('Report name is required');\n  }\n\n  const nameExists = await reportNameExists(item.name, item.id ?? '', true);\n  if (nameExists) {\n    throw new Error('There is already a report named ' + item.name);\n  }\n\n  // Create the report here based on the info\n  await db.insertWithSchema('custom_reports', reportModel.fromJS(item));\n\n  return reportId;\n}\n\nasync function updateReport(item: CustomReportEntity) {\n  if (!item.name) {\n    throw new Error('Report name is required');\n  }\n","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/loot-core/src/server/reports/app.ts#L123-L159","documentation":"Thrown by createReport when the report entity being created has an empty or missing name. Every custom report requires a unique non-empty name used for display and duplicate detection, so the create path explicitly rejects falsy names before checking for name collisions.","triggerScenarios":"Calling createReport (e.g. 'report-create' via the app mutator/API) with a report object whose name is undefined, null, or an empty string — often when the payload is spread-built from partial UI state or a deserialized object lacking name.","commonSituations":"API scripts constructing reports programmatically that forget the name field; importing report JSON from backups/other tools that omitted name; UI state where the name input was never bound into the submitted object.","solutions":["Provide a non-empty name string on the report entity before calling createReport","Validate required fields in your caller code prior to the API call","When importing, map/fallback a default name (e.g. 'Imported report') when name is absent","Check the object you spread into the payload actually contains name"],"exampleFix":"// before\nawait app.createReport({ conditions, conditionsOp: 'and' });\n// after\nawait app.createReport({ name: 'Monthly spending', conditions, conditionsOp: 'and' });","handlingStrategy":"validation","validationCode":"function isNonEmptyString(v: unknown): v is string {\n  return typeof v === 'string' && v.trim().length > 0;\n}\nif (!isNonEmptyString(report.name)) {\n  throw new Error('Report must have a non-empty name before createReport.');\n}","typeGuard":"function hasName(report: CustomReportEntity): report is CustomReportEntity & { name: string } {\n  return typeof report.name === 'string' && report.name.trim().length > 0;\n}","tryCatchPattern":"try {\n  await app.createReport(report);\n} catch (err) {\n  if (err instanceof Error && err.message === 'Report name is required') {\n    await app.createReport({ ...report, name: 'Untitled report' });\n  } else {\n    throw err;\n  }\n}","preventionTips":["Make name a required field in any report-building helper or form schema","Validate payloads (e.g. with zod) before calling createReport","When importing reports, fallback to a generated name when name is absent","Never build payloads by spreading partial state without checking required keys"],"tags":["validation","custom-reports","missing-field"],"backgroundTag":"missing-required-field","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}