{"record":{"id":"23157a5af6e3840a","repo":"hcengineering/platform","slug":"failed-to-find-target-project-type-typeid","errorCode":null,"errorMessage":"Failed to find target project type: ${typeId}","messagePattern":"Failed to find target project type: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/bitrix/src/hr.ts","lineNumber":16,"sourceCode":"import { Organization } from '@hcengineering/contact'\nimport core, { PersonId, Client, Data, Doc, Ref, Status, TxOperations, generateId } from '@hcengineering/core'\nimport recruit, { Applicant, Vacancy } from '@hcengineering/recruit'\nimport task, { ProjectType } from '@hcengineering/task'\n\nexport async function createVacancy (\n  rawClient: Client,\n  name: string,\n  typeId: Ref<ProjectType>,\n  account: PersonId,\n  company?: Ref<Organization>\n): Promise<Ref<Vacancy>> {\n  const client = new TxOperations(rawClient, account)\n  const type = await client.findOne(task.class.ProjectType, { _id: typeId })\n  if (type === undefined) {\n    throw Error(`Failed to find target project type: ${typeId}`)\n  }\n\n  const sequence = await client.findOne(core.class.Sequence, { attachedTo: recruit.class.Vacancy })\n  if (sequence === undefined) {\n    throw new Error('sequence object not found')\n  }\n\n  const incResult = await client.update(sequence, { $inc: { sequence: 1 } }, true)\n\n  const id: Ref<Vacancy> = generateId()\n  await client.createDoc(\n    recruit.class.Vacancy,\n    core.space.Space,\n    {\n      name,\n      description: type.shortDescription ?? '',\n      fullDescription: null,\n      private: false,","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/plugins/bitrix/src/hr.ts#L1-L34","documentation":"createVacancy looks up the Recruit ProjectType document by the given typeId before creating a Vacancy attached to it. If no ProjectType with that _id exists in the workspace, the function throws instead of creating a vacancy referencing a nonexistent type. This guards referential integrity between vacancies and their project types.","triggerScenarios":"Calling createVacancy with a typeId that does not exist in task.class.ProjectType: a stale/deleted type id, an id from another workspace/account, a mistyped or truncated Ref, or calling before any project types were seeded.","commonSituations":"Migrating or restoring data where ProjectType documents were not copied; passing a hardcoded type id after it was deleted or re-created with a new id; running in a fresh workspace without the default Recruit project types created by setup; cross-workspace id reuse.","solutions":["Verify the typeId exists: await client.findOne(task.class.ProjectType, { _id: typeId }) and log the result before calling createVacancy","Fetch available project types for the workspace and pick the correct _id dynamically instead of hardcoding","If migrating data, ensure ProjectType documents are created (e.g. via recruit plugin setup/seed) before creating vacancies","Check you are connected to the correct workspace/account; ids are not globally unique across workspaces"],"exampleFix":"// before\nawait createVacancy(typeId, account, company) // typeId from old DB\n// after\nconst type = await client.findOne(task.class.ProjectType, { _id: typeId })\nif (type === undefined) throw new Error(`ProjectType ${typeId} missing; re-seed types`)\nawait createVacancy(type._id, account, company)","handlingStrategy":"validation","validationCode":"const type = await client.findOne(task.class.ProjectType, { _id: typeId })\nif (type === undefined) {\n  throw new Error(`ProjectType ${typeId} not found in workspace; create/select a valid type first`)\n}\nawait createVacancy(typeId, account, company)","typeGuard":"function isProjectType(t: ProjectType | undefined): t is ProjectType {\n  return t !== undefined\n}","tryCatchPattern":"try {\n  await createVacancy(typeId, account, company)\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('Failed to find target project type')) {\n    const types = await client.findAll(task.class.ProjectType, {})\n    throw new Error(`typeId ${typeId} invalid; available: ${types.map(t => t._id).join(', ')}`)\n  }\n  throw err\n}","preventionTips":["Resolve typeId dynamically from findAll(task.class.ProjectType) instead of hardcoding ids","Ensure the recruit plugin setup/seed ran so default project types exist","When migrating workspaces, copy ProjectType documents before vacancies","Log the fetched type before use to catch stale ids early"],"tags":["recruit","referential-integrity","data-setup","hr"],"backgroundTag":"missing-project-type","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}