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
- Inspect the failing attachment record (log workspaceData.attachments before the loop) and identify which of the three fields is undefined
- 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)
- 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
- 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
- Validate the full export/ImportWorkspace shape before starting the import
- Ensure the source adapter skips (with a warning) attachments whose parent doc could not be resolved
- Log the index and name of each attachment processed so failures are locatable
- Keep exporter and importer versions in sync
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
- Unsupported card type: ${cardType} in ${cardPath}
- Invalid master tag data
- Invalid tag data
- Unsupported type: ${property.type} ${currentPath}
- Blob file not found: ${blobPath} from:${cardPath}
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/6ed45224d8e19bde.
Report an issue: GitHub.