actualbudget/actual · error · CompileError

Invalid field "${name}", are you trying to select a function

Error message

Invalid field "${name}", are you trying to select a function? You need to name the expression

What it means

When compiling the select list, an entry that is an object must map an alias to an expression. If the object's key starts with `$` (i.e. it is a function/expression object used as a field), the compiler rejects it: every computed select expression must be given an explicit output name. This prevents producing SQL columns with no alias.

Source

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

          return fields
            .map(field => {
              const compiled = compileExpr(state, '$' + field);
              state.outputTypes.set(field, compiled.type);
              return compiled.value + ' AS ' + quoteAlias(field);
            })
            .join(', ');
        }

        const compiled = compileExpr(state, '$' + expr);
        state.outputTypes.set(expr, compiled.type);
        return compiled.value + ' AS ' + quoteAlias(expr);
      }

      const [name, value] = Object.entries(expr)[0];
      if (name[0] === '$') {
        state.compileStack.push({ type: 'value', value: expr });
        throw new CompileError(
          `Invalid field "${name}", are you trying to select a function? You need to name the expression`,
        );
      }

      if (typeof value === 'string') {
        const compiled = compileExpr(state, '$' + value);
        state.outputTypes.set(name, compiled.type);
        return `${compiled.value} AS ${quoteAlias(name)}`;
      }

      const compiled = compileFunction({ ...state, orders }, value);
      state.outputTypes.set(name, compiled.type);
      return compiled.value + ` AS ${quoteAlias(name)}`;
    });

    return select.join(', ');
  },
);

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Name the expression by wrapping it: `{month: {$month: '$date'}}`.
  2. Only use `$`-prefixed keys as the value side of the select mapping, not the key.
  3. If you want the raw field, select it as a string: `.select('date')` or `{date: 'date'}`.

Example fix

// before
.select({$month: '$date'})
// after
.select({month: {$month: '$date'}})
Defensive patterns

Strategy: validation

Validate before calling

function assertNamedSelects(selects) {
  for (const s of selects) {
    if (typeof s === 'object' && s !== null && Object.keys(s).some(k => k.startsWith('$'))) {
      throw new Error('Computed select expressions must be named: {alias: {...}}');
    }
  }
}

Type guard

const isNamedSelect = (s) => typeof s === 'object' && s !== null && Object.keys(s).every(k => !k.startsWith('$'));

Prevention

When it happens

Trigger: Writing `.select({$month: '$date'})` or `.select({'$count': ...})` in the select list without wrapping it as `{alias: {$month: '$date'}}`.

Common situations: Trying to select a computed value directly (as in SQL `SELECT month(date)`), forgetting that AQL requires named expressions in the select list.

Related errors


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