actualbudget/actual · error · ValidationError
${name} is missing field ${String(field)}
Error message
${name} is missing field ${String(field)} What it means
requiredFields validates that a model row contains all required fields before database writes via validate(). For inserts (update=false) every listed field must exist and be non-null; for updates, a present field must not be null. Violations throw a ValidationError naming the model and the missing field, e.g. 'transactions is missing field account'.
Source
Thrown at packages/loot-core/src/server/models.ts:32
import type {
DbAccount,
DbAccountGroup,
DbCategory,
DbCategoryGroup,
DbPayee,
} from './db';
import { ValidationError } from './errors';
export function requiredFields<T extends object, K extends keyof T>(
name: string,
row: T,
fields: K[],
update?: boolean,
) {
fields.forEach(field => {
if (update) {
if (row.hasOwnProperty(field) && row[field] == null) {
throw new ValidationError(`${name} is missing field ${String(field)}`);
}
} else {
if (!row.hasOwnProperty(field) || row[field] == null) {
throw new ValidationError(`${name} is missing field ${String(field)}`);
}
}
});
}
export function toDateRepr(str: string) {
if (typeof str !== 'string') {
throw new Error('toDateRepr not passed a string: ' + str);
}
return parseInt(str.replace(/-/g, ''));
}
export function fromDateRepr(number: number) {View on GitHub (pinned to d4334cb6e6)
Solutions
- Read the validation message to see which model and field failed, then include that field with a valid non-null value in your call.
- For transaction adds, always pass account (id or name resolvable), date, and amount.
- For updates, omit fields you don't intend to change instead of sending null.
- If you believe the field should be optional, check the model definition in packages/loot-core/src/server/models.ts to confirm the required list before filing an issue.
Example fix
// before
await api.addTransactions('My Account', [{ date: '2026-08-28', amount: -1234 }]);
// error: transactions is missing field account (id mismatch) — resolve by name to id
// after
const acct = await api.getAccount('My Account');
await api.addTransactions(acct.id, [{ date: '2026-08-28', amount: -1234 }]); Defensive patterns
Strategy: try-catch
Validate before calling
const REQUIRED = { transactions: ['account','date','amount'] };
function validateRow(model, row) {
for (const f of REQUIRED[model] || []) {
if (row?.[f] == null) throw new ValidationError(`${model} is missing field ${f}`);
}
} Type guard
function hasRequiredFields(row, fields) {
return typeof row === 'object' && row !== null &&
fields.every(f => f in row && row[f] != null);
} Try / catch
try {
await api.addTransactions(accountId, txs);
} catch (e) {
if (e.name === 'ValidationError' && e.message.includes('is missing field')) {
const field = e.message.split('missing field ')[1];
// supply the missing field and retry
} else throw e;
} Prevention
- Check the model's required field list in packages/loot-core/src/server/models.ts before scripting inserts.
- For updates, omit unchanged fields rather than sending null.
- Wrap API automation in validation that asserts required fields exist before calls.
- Keep integrations updated when upgrading Actual, as required field sets can change.
When it happens
Trigger: Calling model APIs (e.g. transactions-add, account-create, schedule or payee creation via the API/app) with an object that omits a required field or explicitly sets it to null/undefined — such as adding a transaction without account, or creating an account without name/balance fields.
Common situations: Scripting the @actual-app/api and forgetting mandatory fields; custom importers building rows incompletely; plugins or automation passing partial update objects where a null slipped in; version changes making a previously optional field required.
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
- Unknown payee name normalization: ${String(normalization)}
- `date` is required when adding a transaction
- Amount is invalid, must be an integer: ${trans.amount}
- Category '${category.name}' already exists in group '${categ
- An '${existingGroup.name}' account group already exists.
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/db326dab468291f0.
Report an issue: GitHub.