{"record":{"id":"a10c10fd80d31bec","repo":"hcengineering/platform","slug":"attribute-not-found-key-cardpath","errorCode":null,"errorMessage":"Attribute not found: ${key}, ${cardPath}","messagePattern":"Attribute not found: (.+?), (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/importer/src/huly/cards.ts","lineNumber":561,"sourceCode":"          throw new Error('Blob file not found: ' + blobPath + ' from:' + cardPath)\n        }\n        blobProps[blobFile._id] = {\n          file: blobFile._id,\n          type: blobFile.type,\n          name: blobFile.name,\n          size: blobFile.size,\n          metadata: {} // todo: blobFile.metadata\n        }\n      }\n      cardProps.blobs = blobProps\n    }\n\n    const relations: UnifiedDoc<Doc>[] = []\n    for (const [key, value] of Object.entries(customProperties)) {\n      if (masterTagAttributes.has(key)) {\n        const attr = masterTagAttributes.get(key)\n        if (attr === undefined) {\n          throw new Error(`Attribute not found: ${key}, ${cardPath}`)\n        }\n\n        const attrProps = attr.props\n\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]","sourceCodeStart":543,"sourceCodeEnd":579,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/packages/importer/src/huly/cards.ts#L543-L579","documentation":"A defensive check inside createCardWithRelations: after masterTagAttributes.has(key) returns true, the map get() should never be undefined. Throwing here signals a race/modification between the has-check and the get, or a custom map implementation with inconsistent behavior.","triggerScenarios":"Effectively unreachable in normal use — the key was just confirmed present in masterTagAttributes. It could only fire if masterTagAttributes is mutated concurrently, is a Map-like object whose has/get disagree, or a custom subclass overrides one of the methods inconsistently.","commonSituations":"Custom concurrency where another async task clears/rebuilds the attributes map mid-processing; wrapping the map in a proxy or passing a plain object masquerading as a Map.","solutions":["Audit for concurrent mutation of masterTagAttributes during processing and snapshot the map before iterating cards.","Ensure a genuine Map is passed (not a Map-like wrapper with divergent has/get).","Log the key and map contents at failure to identify what removed the entry."],"exampleFix":"// before\nawait Promise.all(cards.map(c => this.processCard(c, masterTagAttributes)))\n// after — snapshot to avoid concurrent mutation\nconst attrsSnapshot = new Map(masterTagAttributes)\nawait Promise.all(cards.map(c => this.processCard(c, attrsSnapshot)))","handlingStrategy":"try-catch","validationCode":"import fs from 'fs'\nfunction hasMasterTagAttr(attrs: Map<string, unknown>, key: string): boolean {\n  return attrs instanceof Map && attrs.has(key)\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('Attribute not found:')) {\n    console.error('masterTagAttributes was mutated or replaced mid-import — snapshot maps before processing')\n  } else throw e\n}","preventionTips":["Don't mutate processor maps while an import is running; pass immutable snapshots.","Ensure attributes are fully built before processing cards that reference them.","Pass genuine Map instances, not proxies or Map-like wrappers."],"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"}