{"record":{"id":"f5826663be4b3a4a","repo":"actualbudget/actual","slug":"can-t-convert-expr-type-to-type","errorCode":null,"errorMessage":"Can't convert ${expr.type} to ${type}","messagePattern":"Can't convert (.+?) to (.+?)","errorType":"exception","errorClass":"CompileError","httpStatus":null,"severity":"error","filePath":"packages/loot-core/src/server/aql/compiler.ts","lineNumber":339,"sourceCode":"        `CAST(SUBSTR(${expr2.value}, 1, 4) AS integer)`,\n        'date-year',\n      );\n    }\n  } else if (type === 'id') {\n    if (expr.type === 'string') {\n      return typed(expr.value, 'id', { literal: expr.literal });\n    }\n  } else if (type === 'float') {\n    if (expr.type === 'integer') {\n      return typed(expr.value, 'float', { literal: expr.literal });\n    }\n  }\n\n  if (expr.type === 'any') {\n    return typed(expr.value, type, { literal: expr.literal });\n  }\n\n  throw new CompileError(`Can't convert ${expr.type} to ${type}`);\n}\n\n// TODO: remove state from these functions\nfunction val(state, expr, type?: string) {\n  let castedExpr = expr;\n\n  // Cast the type if necessary\n  if (type) {\n    castedExpr = castInput(state, expr, type);\n  }\n\n  if (castedExpr.literal) {\n    if (castedExpr.type === 'id') {\n      return `'${castedExpr.value}'`;\n    } else if (castedExpr.type === 'string') {\n      // Escape quotes\n      const value = castedExpr.value.replace(/'/g, \"''\");\n      return `'${value}'`;","sourceCodeStart":321,"sourceCodeEnd":357,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/loot-core/src/server/aql/compiler.ts#L321-L357","documentation":"Generic cast failure at the end of castInput: after all specific cast branches (date casts, id-from-string, integer-to-float, `any` passthrough) none applied, so the expression's type cannot be converted to the requested type. This catches combinations with no defined cast, e.g. boolean to float or array to id.","triggerScenarios":"Requesting a cast between unrelated types: e.g. string to float (strings don't auto-cast to numeric), boolean to date/id, array to any scalar type, date to id. Triggered via val(), compileFunction(), compileOp() when the function schema requires a type the argument can't supply.","commonSituations":"Passing numeric values as strings ('100' where 100 is needed); passing an array where a scalar is required ($in misuse with nested arrays); custom functions declaring parameter types the caller can't satisfy.","solutions":["Pass the value already in the target type (e.g. number instead of string) for numeric casts","Use a string for id/`date` targets — those are the castable string paths","Unwrap single-element arrays and pass the scalar directly","Adjust the function schema/type declaration if you control it so the argument type matches"],"exampleFix":"// before\nq.filter({ amount: { $gt: '100' } })\n// after\nq.filter({ amount: { $gt: 100 } })","handlingStrategy":"type-guard","validationCode":"if (typeof value === 'string' && ['float','integer','boolean'].includes(targetType)) {\n  throw new Error(`Strings don't auto-cast to ${targetType}; convert first`);\n}","typeGuard":"function isCastable(value, targetType) {\n  const t = Array.isArray(value) ? 'array' : value === null ? 'null' : typeof value === 'object' ? (value instanceof Date ? 'date' : 'object') : typeof value;\n  const ok = {\n    id: ['string'], float: ['integer'], integer: [], boolean: [],\n    date: ['string'], 'date-month': ['string'], 'date-year': ['string'],\n  };\n  return t === targetType || (ok[targetType] || []).includes(t);\n}","tryCatchPattern":"try {\n  runQuery(query);\n} catch (e) {\n  if (/Can't convert .* to /.test(e.message)) {\n    throw new Error('Type mismatch in query: convert the value to the target type before querying', { cause: e });\n  }\n  throw e;\n}","preventionTips":["Supply values in the exact target type (numbers for numeric comparisons)","Know the limited cast table: string->id, integer->float, string->date family, any passthrough","Unwrap arrays before passing scalars"],"tags":["aql","query-compiler","type-cast"],"backgroundTag":"aql-type-cast-error","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}