{"record":{"id":"8dc40c08cd4b2076","repo":"hcengineering/platform","slug":"association-not-found-key-cardpath","errorCode":null,"errorMessage":"Association not found: ${key}, ${cardPath}","messagePattern":"Association not found: (.+?), (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/importer/src/huly/cards.ts","lineNumber":583,"sourceCode":"\n        const attrType = attrProps.type\n        const attrBaseType = attrType._class === core.class.ArrOf ? attrType.of : attrType\n        const values = attrType._class === core.class.ArrOf ? value : [value]\n        const propValues = []\n        for (const val of values) {\n          if (attrBaseType._class === core.class.RefTo) {\n            const refPath = path.resolve(path.dirname(cardPath), val)\n            const ref = this.metadataRegistry.getRef(refPath) as Ref<Card>\n            propValues.push(ref)\n          } else {\n            propValues.push(val)\n          }\n        }\n        cardProps[attrProps.name] = attrType._class === core.class.ArrOf ? propValues : propValues[0]\n      } else if (masterTagAssociaions.has(key) || tagAssociations.has(key)) {\n        const metadata = masterTagAssociaions.get(key) ?? tagAssociations.get(key)\n        if (metadata === undefined) {\n          throw new Error(`Association not found: ${key}, ${cardPath}`)\n        }\n        const values = Array.isArray(value) ? value : [value]\n        for (const val of values) {\n          const otherCardPath = path.resolve(path.dirname(cardPath), val)\n          const otherCardId = this.metadataRegistry.getRef(otherCardPath) as Ref<Card>\n          const relation: UnifiedDoc<Relation> = this.createRelation(metadata, cardId, otherCardId)\n          relations.push(relation)\n        }\n      }\n    }\n\n    return [\n      {\n        _class: masterTagId,\n        collabField: 'content',\n        contentProvider: () => Promise.resolve(this.parser.readMarkdownContent(cardPath)),\n        props: cardProps as Props<Card>\n      },","sourceCodeStart":565,"sourceCodeEnd":601,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/packages/importer/src/huly/cards.ts#L565-L601","documentation":"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.","triggerScenarios":"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.","commonSituations":"Multi-threaded or interleaved async import pipelines sharing processor state; custom caching layer around the association maps.","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."],"exampleFix":"// before\nconst metadata = masterTagAssociaions.get(key) ?? tagAssociations.get(key)\n// after — guard with explicit lookup\nconst metadata = masterTagAssociaions.get(key) ?? tagAssociations.get(key)\nif (metadata === undefined) throw new Error(`Association not found: ${key}, ${cardPath}`)","handlingStrategy":"try-catch","validationCode":"function associationsReady(a: Map<string, unknown>, t: Map<string, unknown>, keys: string[]): string[] {\n  return keys.filter(k => !a.has(k) && !t.has(k))\n}","typeGuard":"function isRealMap<K, V>(m: unknown): m is Map<K, V> {\n  return m instanceof Map\n}","tryCatchPattern":"try {\n  await processor.cardWithRelations(cardPath)\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Association not found:')) {\n    console.error('Association maps were mutated or built after cards were processed — build associations first, then snapshot')\n  } else throw e\n}","preventionTips":["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."],"tags":["importer","defensive-check","internal-invariant"],"backgroundTag":"map-entry-missing","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}