actualbudget/actual · error · Error

Report name is required

Error message

Report name is required

What it means

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.

Source

Thrown at packages/loot-core/src/server/reports/app.ts:141

    then no name change was made.
    -if they are not the same then there is another
    item with that name already.
    */
    return idForName.id !== reportId;
  }

  //default return: item was found but does not match current name
  return true;
}

async function createReport(report: CustomReportEntity) {
  const reportId = uuidv4();
  const item: CustomReportEntity = {
    ...report,
    id: reportId,
  };
  if (!item.name) {
    throw new Error('Report name is required');
  }

  const nameExists = await reportNameExists(item.name, item.id ?? '', true);
  if (nameExists) {
    throw new Error('There is already a report named ' + item.name);
  }

  // Create the report here based on the info
  await db.insertWithSchema('custom_reports', reportModel.fromJS(item));

  return reportId;
}

async function updateReport(item: CustomReportEntity) {
  if (!item.name) {
    throw new Error('Report name is required');
  }

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Provide a non-empty name string on the report entity before calling createReport
  2. Validate required fields in your caller code prior to the API call
  3. When importing, map/fallback a default name (e.g. 'Imported report') when name is absent
  4. Check the object you spread into the payload actually contains name

Example fix

// before
await app.createReport({ conditions, conditionsOp: 'and' });
// after
await app.createReport({ name: 'Monthly spending', conditions, conditionsOp: 'and' });
Defensive patterns

Strategy: validation

Validate before calling

function isNonEmptyString(v: unknown): v is string {
  return typeof v === 'string' && v.trim().length > 0;
}
if (!isNonEmptyString(report.name)) {
  throw new Error('Report must have a non-empty name before createReport.');
}

Type guard

function hasName(report: CustomReportEntity): report is CustomReportEntity & { name: string } {
  return typeof report.name === 'string' && report.name.trim().length > 0;
}

Try / catch

try {
  await app.createReport(report);
} catch (err) {
  if (err instanceof Error && err.message === 'Report name is required') {
    await app.createReport({ ...report, name: 'Untitled report' });
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


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