hcengineering/platform · error · Error

Attachment is missing parentId, parentClass or spaceId

Error message

Attachment is missing parentId, parentClass or spaceId

What it means

During import, the importer validates that every attachment record carries the three fields required to attach it in the target workspace: parentId (the doc it attaches to), parentClass (the class of that doc), and spaceId (the owning space). If any is undefined, the import is aborted with this error before any upload is attempted, because an attachment without these cannot be placed via client.addCollection.

Source

Thrown at packages/importer/src/importer/importer.ts:330

        await this.importTeamspace(space as ImportTeamspace)
      } else if (space.class === tracker.class.Project) {
        await this.importProject(space as ImportProject)
      } else if (space.class === documents.class.OrgSpace) {
        await this.importOrgSpace(space as ImportOrgSpace)
      }
    }
  }

  private async importAttachments (): Promise<void> {
    if (this.workspaceData.attachments === undefined) return

    for (const attachment of this.workspaceData.attachments) {
      if (
        attachment.parentId === undefined ||
        attachment.parentClass === undefined ||
        attachment.spaceId === undefined
      ) {
        throw new Error('Attachment is missing parentId, parentClass or spaceId')
      }
      await this.importAttachment(attachment.parentId, attachment.parentClass, attachment, attachment.spaceId)
    }
  }

  async createProjectTypeWithTaskTypes (projectType: ImportProjectType): Promise<Ref<ProjectType>> {
    const taskTypes: TaskTypeWithFactory[] = []
    if (projectType.taskTypes !== undefined) {
      for (const taskType of projectType.taskTypes) {
        const taskTypeId = generateId<TaskType>()
        const statuses = taskType.statuses.map((status) => {
          return {
            name: status.name,
            ofAttribute: tracker.attribute.IssueStatus,
            category: task.statusCategory.Active
          }
        })
        taskTypes.push({

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Inspect the failing attachment record (log workspaceData.attachments before the loop) and identify which of the three fields is undefined
  2. Fix the source adapter/export so it resolves parentId, parentClass and spaceId for every attachment (skip or drop attachments whose parent could not be resolved)
  3. If manually editing import data, set parentClass to the parent doc's class (e.g. 'tracker:class:Issue') and spaceId to the target project/space Ref
  4. Upgrade to a matching exporter/importer version pair so attachment shapes agree

Example fix

// before
{ name: 'screenshot.png', data: fileBlob } // missing parentId/spaceId
// after
{ name: 'screenshot.png', data: fileBlob, parentId: issueId, parentClass: 'tracker:class:Issue', spaceId: projectId }
Defensive patterns

Strategy: validation

Validate before calling

function validateAttachment(a) {
  const missing = ['parentId', 'parentClass', 'spaceId'].filter(k => a[k] === undefined)
  if (missing.length > 0) throw new Error(`Attachment ${a.name ?? a._id} missing: ` + missing.join(', '))
}
workspaceData.attachments.forEach(validateAttachment)

Type guard

function hasAttachmentRefs(a): a is typeof a & { parentId: NonNullable<typeof a.parentId>, parentClass: NonNullable<typeof a.parentClass>, spaceId: NonNullable<typeof a.spaceId> } {
  return a.parentId !== undefined && a.parentClass !== undefined && a.spaceId !== undefined
}

Try / catch

try {
  await importer.importAttachments()
} catch (err) {
  if (err.message.includes('Attachment is missing')) {
    console.error('Malformed import data:', err.message)
  } else throw err
}

Prevention

When it happens

Trigger: workspaceData.attachments contains an entry built by a source-adapter (e.g. GitHub/Jira export) that failed to resolve the issue/doc or space the attachment belongs to, leaving parentId, parentClass or spaceId undefined; or a hand-written ImportAttachment object omitted one of the fields.

Common situations: Importing an export where an attachment referenced a deleted/unknown issue so the converter could not backfill its parent; migrating between tracker versions where the attachment shape gained required fields; manually editing exported JSON and dropping a field.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


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