hcengineering/platform · error
Association not found: ${key}, ${cardPath}
Error message
Association not found: ${key}, ${cardPath} What it means
Same defensive pattern as the attribute check, but for associations: the key matched masterTagAssociaions or tagAssociations via has(), yet get() returned undefined. In practice it indicates concurrent map mutation or an inconsistent Map-like implementation, since the has-check just succeeded.
Source
Thrown at packages/importer/src/huly/cards.ts:583
const attrType = attrProps.type
const attrBaseType = attrType._class === core.class.ArrOf ? attrType.of : attrType
const values = attrType._class === core.class.ArrOf ? value : [value]
const propValues = []
for (const val of values) {
if (attrBaseType._class === core.class.RefTo) {
const refPath = path.resolve(path.dirname(cardPath), val)
const ref = this.metadataRegistry.getRef(refPath) as Ref<Card>
propValues.push(ref)
} else {
propValues.push(val)
}
}
cardProps[attrProps.name] = attrType._class === core.class.ArrOf ? propValues : propValues[0]
} else if (masterTagAssociaions.has(key) || tagAssociations.has(key)) {
const metadata = masterTagAssociaions.get(key) ?? tagAssociations.get(key)
if (metadata === undefined) {
throw new Error(`Association not found: ${key}, ${cardPath}`)
}
const values = Array.isArray(value) ? value : [value]
for (const val of values) {
const otherCardPath = path.resolve(path.dirname(cardPath), val)
const otherCardId = this.metadataRegistry.getRef(otherCardPath) as Ref<Card>
const relation: UnifiedDoc<Relation> = this.createRelation(metadata, cardId, otherCardId)
relations.push(relation)
}
}
}
return [
{
_class: masterTagId,
collabField: 'content',
contentProvider: () => Promise.resolve(this.parser.readMarkdownContent(cardPath)),
props: cardProps as Props<Card>
},View on GitHub (pinned to 63e28dc964)
Solutions
- Snapshot both association maps before the card-processing loop to isolate from concurrent rebuilds.
- Serialize processing stages so associations are fully built before cards referencing them are processed.
- Replace any Map-like wrapper with a real Map.
Example fix
// before
const metadata = masterTagAssociaions.get(key) ?? tagAssociations.get(key)
// after — guard with explicit lookup
const metadata = masterTagAssociaions.get(key) ?? tagAssociations.get(key)
if (metadata === undefined) throw new Error(`Association not found: ${key}, ${cardPath}`) Defensive patterns
Strategy: try-catch
Validate before calling
function associationsReady(a: Map<string, unknown>, t: Map<string, unknown>, keys: string[]): string[] {
return keys.filter(k => !a.has(k) && !t.has(k))
} Type guard
function isRealMap<K, V>(m: unknown): m is Map<K, V> {
return m instanceof Map
} Try / catch
try {
await processor.cardWithRelations(cardPath)
} catch (e) {
if (e instanceof Error && e.message.startsWith('Association not found:')) {
console.error('Association maps were mutated or built after cards were processed — build associations first, then snapshot')
} else throw e
} Prevention
- Build all associations before processing cards that reference them.
- Snapshot association maps (new Map(...)) before parallel card processing.
- Avoid sharing mutable association maps across concurrent import pipelines.
When it happens
Trigger: masterTagAssociaions/tagAssociations rebuilt or cleared while createCardWithRelations is executing (e.g. parallel processing of directories sharing the maps); passing proxy/wrapper objects where has() and get() disagree.
Common situations: Multi-threaded or interleaved async import pipelines sharing processor state; custom caching layer around the association maps.
Related errors
- Attribute not found: ${key}, ${cardPath}
- Unsupported card type: ${cardType} in ${cardPath}
- Invalid master tag data
- Invalid tag data
- Unsupported type: ${property.type} ${currentPath}
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/8dc40c08cd4b2076.
Report an issue: GitHub.