hcengineering/platform · error · Error

contact not found

Error message

contact not found

What it means

After incrementing the sequence, CreateReview.svelte fetches the Person the review is attached to via `doc.attachedTo`. If the lookup fails, the candidate cannot be resolved/mixin'd and it throws 'contact not found'. This means the review dialog's attachedTo id does not point to an existing contact.class.Person document.

Source

Thrown at plugins/recruit-resources/src/components/review/CreateReview.svelte:99

  const dispatch = createEventDispatcher()
  const client = getClient()
  const hierarchy = client.getHierarchy()

  export function canClose (): boolean {
    return (preserveCandidate || candidate === undefined) && title.length === 0
  }

  async function createReview () {
    const sequence = await client.findOne(core.class.Sequence, { attachedTo: recruit.class.Review })
    if (sequence === undefined) {
      throw new Error('sequence object not found')
    }

    const incResult = await client.update(sequence, { $inc: { sequence: 1 } }, true)

    const candidateInstance = await client.findOne(contact.class.Person, { _id: doc.attachedTo as Ref<Person> })
    if (candidateInstance === undefined) {
      throw new Error('contact not found')
    }
    if (!client.getHierarchy().hasMixin(candidateInstance, recruit.mixin.Candidate)) {
      await client.createMixin<Person, Candidate>(
        candidateInstance._id,
        candidateInstance._class,
        candidateInstance.space,
        recruit.mixin.Candidate,
        {}
      )
    }

    const ref = await client.addCollection(
      recruit.class.Review,
      doc.space,
      doc.attachedTo,
      doc.attachedToClass,
      'reviews',
      {

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Refresh client data and reopen the review dialog with a valid candidate.
  2. Include the failing id in the error message to diagnose the broken reference.
  3. Validate before submission that doc.attachedTo resolves to an existing Person.
  4. Check whether the candidate was soft-deleted or filtered out by permissions.

Example fix

// before
const candidateInstance = await client.findOne(contact.class.Person, { _id: doc.attachedTo as Ref<Person> })
if (candidateInstance === undefined) {
  throw new Error('contact not found')
}
// after
const candidateInstance = await client.findOne(contact.class.Person, { _id: doc.attachedTo as Ref<Person> })
if (candidateInstance === undefined) {
  throw new Error(`person not found: ${String(doc.attachedTo)}`)
}
Defensive patterns

Strategy: type-guard

Validate before calling

const person = await client.findOne(contact.class.Person, { _id: doc.attachedTo as Ref<Person> })
if (person === undefined) {
  console.error('person missing', doc.attachedTo)
  return
}

Type guard

function personExists(p: Person | undefined): p is Person { return p !== undefined }

Try / catch

try {
  await createReview()
} catch (e) {
  if (e.message === 'contact not found') {
    showNotification('The candidate no longer exists; refresh and reopen the dialog')
  } else throw e
}

Prevention

When it happens

Trigger: Creating a review when `client.findOne(contact.class.Person, { _id: doc.attachedTo })` returns undefined — the person was deleted, the id is stale, or the doc.attachedTo points at a non-Person document.

Common situations: Candidate deleted by another user while the review dialog was open; stale/offline client cache; dialog opened from a wrong context passing a non-person id; permission filtering hiding the person record.

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/4870723cf5d1986b. Report an issue: GitHub.