actualbudget/actual · critical

Error updating: table "${table}" does not exist

Error message

Error updating: table "${table}" does not exist

What it means

convertForUpdate checks the table exists in the schema before delegating to conform; an unknown table during update throws 'Error updating: table "X" does not exist'. This is the update-path twin of the insert table check (error 217).

Source

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

        throw new Error(
          `"${field}" is required for table "${table}": ${JSON.stringify(obj)}`,
        );
      }
    }
  });

  // We use `skipNull` to remove any null values. There's no need to
  // set those when inserting, that will be the default and it reduces
  // the amount of messages generated to sync
  return conform(schema, schemaConfig, table, obj, { skipNull: true });
}

export function convertForUpdate(schema, schemaConfig, table, rawObj) {
  const obj = { ...rawObj };

  const tableSchema = schema[table];
  if (tableSchema == null) {
    throw new Error(`Error updating: table "${table}" does not exist`);
  }

  return conform(schema, schemaConfig, table, obj);
}

export function convertFromSelect(schema, schemaConfig, table, obj) {
  const tableSchema = schema[table];
  if (tableSchema == null) {
    throw new Error(`Table "${table}" does not exist`);
  }

  const fields = Object.keys(tableSchema);
  const result = {};
  for (let i = 0; i < fields.length; i++) {
    const fieldName = fields[i];
    const fieldDesc = tableSchema[fieldName];

    result[fieldName] = convertOutputType(obj[fieldName], fieldDesc.type);

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Fix the table name to one registered in the aql schema (e.g. 'transactions').
  2. Verify against the schema source which tables exist and their exact names.
  3. Update the code after any schema rename (check release notes / git history of the schema file).
  4. Confirm the `schema` argument is the real schema map, not a mock or partial object missing the table.

Example fix

// before
updateWithSchema('payees ', id, obj); // trailing space
// after
updateWithSchema('payees', id, obj);
Defensive patterns

Strategy: validation

Validate before calling

const VALID_UPDATE_TABLES = new Set(Object.keys(schema));
function safeUpdate(table, obj) {
  if (!VALID_UPDATE_TABLES.has(table)) throw new Error(`Unknown update table: ${table}`);
  return updateWithSchema(table, obj.id, obj);
}

Try / catch

try {
  return updateWithSchema(table, id, obj);
} catch (e) {
  if (e.message.includes('Error updating: table')) {
    logger.error('Update against unknown table', { table });
    return null;
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling convertForUpdate (directly or via updateWithSchema/toDb in a transactor) with a table name not present in the schema map — typos, stale names after renames, or hand-built schema objects missing the table.

Common situations: Update helpers written for tables renamed between Actual versions, plugins touching internal tables, and refactors that changed the table constant string without updating all call sites.

Related errors


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