actualbudget/actual · error · CompileError

Path error: ${tableName} table does not exist

Error message

Path error: ${tableName} table does not exist

What it means

While walking a dotted path, makePath (compiler.ts:81) reduces over each segment, looking up the current table in the schema. If the intermediate table name is not in the schema at all, this CompileError is thrown — the path references a table that does not exist.

Source

Thrown at packages/loot-core/src/server/aql/compiler.ts:85

  }
  return fieldDesc;
}

function makePath(state, path) {
  const { schema, paths } = state;

  const parts = path.split('.');
  if (parts.length < 2) {
    throw new CompileError('Invalid path: ' + path);
  }

  const initialTable = parts[0];

  const tableName = parts.slice(1).reduce((tableName, field) => {
    const table = schema[tableName];

    if (table == null) {
      throw new CompileError(`Path error: ${tableName} table does not exist`);
    }

    if (!table[field] || table[field].ref == null) {
      throw new CompileError(
        `Field not joinable on table ${tableName}: "${field}"`,
      );
    }

    return table[field].ref;
  }, initialTable);

  let joinTable;
  const parentParts = parts.slice(0, -1);
  if (parentParts.length === 1) {
    joinTable = parentParts[0];
  } else {
    const parentPath = parentParts.join('.');
    const parentDesc = paths.get(parentPath);

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Fix the table segment in the path to a valid schema table/relationship name (see aql schema.ts).
  2. Use the documented relationship names: e.g. on transactions use 'payee.name', 'account.name', 'category.name'.
  3. Verify the first path segment is the base table name as defined in the query state, and subsequent segments are joinable refs.

Example fix

// before
q('transactions').select('payees.name')
// after
q('transactions').select('payee.name')
Defensive patterns

Strategy: validation

Validate before calling

import { schema } from './aql/schema';
function assertPathTables(path) {
  const parts = path.split('.');
  let t = parts[0];
  for (const f of parts.slice(1)) {
    if (!schema[t]) throw new Error(`Unknown table ${t} in path ${path}`);
    t = schema[t][f]?.ref;
  }
}

Type guard

function tableExists(name) {
  return Object.prototype.hasOwnProperty.call(schema, name);
}

Try / catch

try {
  runQuery(q);
} catch (e) {
  if (e.message.includes('table does not exist')) {
    throw new Error('Check the relationship name in your field path');
  } else throw e;
}

Prevention

When it happens

Trigger: A path like 'payees.unknownthing.name' or a mistyped first segment reaching makePath via q('transactions').filter({ 'payeesX.name': 'foo' }) — actually triggered when the reduce lands on a tableName missing from schema, e.g. 'account.typo.name'.

Common situations: Typos in the table portion of a relationship path; using plural/singular forms that don't match the schema ('accounts.bank' vs correct relationship names); schema changes between versions removing a join table.

Related errors


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