{"record":{"id":"14e13c8c35881a94","repo":"actualbudget/actual","slug":"invalid-field-reference","errorCode":null,"errorMessage":"Invalid field reference: ","messagePattern":"Invalid field reference: ","errorType":"exception","errorClass":"CompileError","httpStatus":null,"severity":"error","filePath":"packages/loot-core/src/server/aql/compiler.ts","lineNumber":494,"sourceCode":"      literal: true,\n    });\n  } else if (Array.isArray(value)) {\n    return typed(value, 'array', { literal: true });\n  } else {\n    throw new CompileError(\n      'Unsupported type of expression: ' + JSON.stringify(value),\n    );\n  }\n}\n\nconst compileExpr = saveStack('expr', (state, expr) => {\n  if (typeof expr === 'string') {\n    // Field reference\n    if (expr[0] === '$') {\n      const fieldRef = expr === '$' ? state.implicitField : expr.slice(1);\n\n      if (fieldRef == null || fieldRef === '') {\n        throw new CompileError('Invalid field reference: ' + expr);\n      }\n\n      return transformField(state, fieldRef);\n    }\n\n    // Named parameter\n    if (expr[0] === ':') {\n      const param = { value: '?', type: 'param', paramName: expr.slice(1) };\n      state.namedParameters.push(param);\n      return param;\n    }\n  }\n\n  if (expr !== null) {\n    if (Array.isArray(expr)) {\n      return compileLiteral(expr);\n    } else if (\n      typeof expr === 'object' &&","sourceCodeStart":476,"sourceCodeEnd":512,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/loot-core/src/server/aql/compiler.ts#L476-L512","documentation":"In compileExpr, a string expression starting with '$' is treated as a field reference: '$' alone means the implicit field, otherwise the text after '$' is the field name. If the resulting reference is null or empty (e.g. '$' with no implicit field set, or '$' followed by nothing meaningful), CompileError 'Invalid field reference: ...' is thrown.","triggerScenarios":"Using '$' without an implicit field configured in the query state; a string like '$' or a malformed reference that slices to an empty field name; passing '$' where a concrete field like '$date' was intended.","commonSituations":"Hand-written filters using bare '$' in queries where no implicit field applies; dynamic field-name construction that produced an empty string; template strings like `$${field}` where field was empty.","solutions":["Replace '$' with a concrete field reference like '$date'","Set the query's implicit field (e.g. via the appropriate query API) if you intend to use bare '$'","Check dynamic field-name code for empty/undefined values before building the reference","Validate field names against the schema before compiling"],"exampleFix":"// before\nq.filter({ $eq: ['$', 'checking'] }) // no implicit field\n// after\nq.filter({ account: 'checking' }) // or use '$account'","handlingStrategy":"validation","validationCode":"function assertFieldRef(ref, implicitField) {\n  if (typeof ref === 'string' && ref.startsWith('$')) {\n    const name = ref === '$' ? implicitField : ref.slice(1);\n    if (!name) throw new Error(`Invalid field reference: ${ref}`);\n  }\n}","typeGuard":"function isValidFieldRef(ref, implicitField) {\n  if (typeof ref !== 'string' || !ref.startsWith('$')) return true;\n  const name = ref === '$' ? implicitField : ref.slice(1);\n  return name != null && name !== '';\n}","tryCatchPattern":"try {\n  runQuery(query);\n} catch (e) {\n  if (/Invalid field reference/.test(e.message)) {\n    console.error('Use a concrete field like $date or set the implicit field');\n  }\n  throw e;\n}","preventionTips":["Prefer explicit field references ($date) over bare '$'","Ensure implicit field is configured whenever '$' is used","Guard dynamically built field names against empty strings"],"tags":["aql","query-compiler","field-reference"],"backgroundTag":"invalid-field-reference","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}