{"record":{"id":"236064ec30495df3","repo":"actualbudget/actual","slug":"provide-a-valid-type","errorCode":null,"errorMessage":"Provide a valid type","messagePattern":"Provide a valid type","errorType":"validation","errorClass":"APIError","httpStatus":null,"severity":"error","filePath":"packages/loot-core/src/server/api.ts","lineNumber":1097,"sourceCode":"      resetNextDate,\n    });\n  } else {\n    return sched.id;\n  }\n});\n\nhandlers['api/schedule-delete'] = withMutation(async function (id: string) {\n  checkFileOpen();\n  return handlers['schedule/delete']({ id });\n});\n\nhandlers['api/get-id-by-name'] = async function ({ type, name }) {\n  checkFileOpen();\n\n  const allowedTypes = ['payees', 'categories', 'schedules', 'accounts'];\n\n  if (!allowedTypes.includes(type)) {\n    throw APIError('Provide a valid type');\n  }\n\n  const { data } = await aqlQuery(q(type).filter({ name }).select('*'));\n\n  if (!data || data.length === 0) {\n    throw APIError(`Not found: ${type} with name ${name}`);\n  }\n\n  return data[0].id;\n};\n\nhandlers['api/get-server-version'] = async function () {\n  return handlers['get-server-version']();\n};\n\nexport function installAPI(serverHandlers: ServerHandlers) {\n  const merged = Object.assign({}, serverHandlers, handlers);\n  handlers = merged as Handlers;","sourceCodeStart":1079,"sourceCodeEnd":1115,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/loot-core/src/server/api.ts#L1079-L1115","documentation":"The 'api/get-id-by-name' handler resolves a name to an id only for a fixed set of entity types: payees, categories, schedules, accounts. Any other type value throws this APIError before a query is run.","triggerScenarios":"Calling getIdByName with type values like 'payee' (singular), 'transactions', 'rules', null, or undefined.","commonSituations":"Guessing the type string instead of checking the API docs; singular/plural confusion; passing a table name from a different tool's schema.","solutions":["Pass exactly one of: 'payees', 'categories', 'schedules', 'accounts'.","Fix singular/plural mismatches (use 'payees', not 'payee').","Validate/whitelist the type in wrapper code before calling."],"exampleFix":"// before\nawait q.getIdByName('payee', 'Alice');\n// after\nawait q.getIdByName('payees', 'Alice');","handlingStrategy":"validation","validationCode":"const TYPES = ['payees', 'categories', 'schedules', 'accounts'];\nif (!TYPES.includes(type)) throw new Error(`type must be one of ${TYPES.join(', ')}`);\nconst id = await actual.getIdByName(type, name);","typeGuard":"function isLookupType(t) {\n  return ['payees','categories','schedules','accounts'].includes(t);\n}","tryCatchPattern":"try {\n  const id = await actual.getIdByName(type, name);\n} catch (e) {\n  if (String(e.message) === 'Provide a valid type') {\n    console.error('Use plural type names: payees, categories, schedules, accounts');\n  } else throw e;\n}","preventionTips":["Remember types are plural","Centralize the allowed-type list in your integration","Type the parameter with the union type"],"tags":["api","validation","invalid-argument"],"backgroundTag":"invalid-enum-value","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}