actualbudget/actual · error

"${field}" is required for table "${table}": ${JSON.stringif

Error message

"${field}" is required for table "${table}": ${JSON.stringify(obj)}

What it means

conform enforces that required fields (those marked required in the schema, plus 'id') are present and non-null in the object being written. A required field that is null or undefined aborts the operation with a message naming the field, table, and full object.

Source

Thrown at packages/loot-core/src/server/aql/schema-helpers.ts:128

  return Object.fromEntries(
    Object.keys(obj)
      .map(field => {
        // Fields that start with an underscore are ignored
        if (field[0] === '_') {
          return null;
        }

        const fieldDesc = tableSchema[field];
        if (fieldDesc == null) {
          throw new Error(
            `Field "${field}" does not exist on table ${table}: ${JSON.stringify(
              obj,
            )}`,
          );
        }

        if (isRequired(field, fieldDesc) && obj[field] == null) {
          throw new Error(
            `"${field}" is required for table "${table}": ${JSON.stringify(
              obj,
            )}`,
          );
        }

        // treat undefined as missing
        if (obj[field] === undefined) {
          return null;
        }

        // This option removes null values (see `convertForInsert`)
        if (skipNull && obj[field] == null) {
          return null;
        }

        return [fieldRef(field), convertInputType(obj[field], fieldDesc.type)];
      })

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Provide a valid value for the required field before writing.
  2. For partial updates, merge with the existing record first: `{ ...existing, ...changes }`.
  3. Validate input at your API/import boundary and reject incomplete rows with a clearer message.
  4. If the field should not actually be required, update the schema definition (with care).

Example fix

// before
convertForUpdate(schema, schemaConfig, 'transactions', { id, amount }); // date missing
// after
const existing = await getTransaction(id);
convertForUpdate(schema, schemaConfig, 'transactions', { ...existing, amount });
Defensive patterns

Strategy: validation

Validate before calling

function requireFields(obj, fields) {
  for (const f of fields) {
    if (obj[f] == null) throw new Error(`Missing required field: ${f}`);
  }
}
requireFields(txn, ['id', 'account', 'date']);

Try / catch

try {
  return convertForUpdate(schema, schemaConfig, table, obj);
} catch (e) {
  if (e.message.includes('is required for table')) {
    logger.error('Required field missing', { obj });
    return { ok: false, reason: e.message };
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling convertForUpdate/conform with an object missing a required field such as a transaction's 'date' or 'account', or with that field explicitly set to null.

Common situations: Partial updates where the caller assumed only changed fields are needed but the required field was absent, import pipelines producing rows with null dates/accounts, and forms that allow submitting without selecting an account.

Related errors


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