{"record":{"id":"10e433467371ad26","repo":"hcengineering/platform","slug":"variable-matched-0-not-found-10e433","errorCode":null,"errorMessage":"Variable ${matched[0]} not found","messagePattern":"Variable (.+?) not found","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/tool/src/initializer.ts","lineNumber":386,"sourceCode":"      if (Array.isArray(value)) {\n        return await Promise.all(value.map(async (v) => await this.fillValue(v, vars)))\n      } else {\n        return await this.fillProps(value, vars)\n      }\n    } else if (typeof value === 'string') {\n      if (value === this.nextRank) {\n        const rank = makeRank(vars[this.nextRank], undefined)\n        vars[this.nextRank] = rank\n        return rank\n      } else if (value === this.now) {\n        return new Date().getTime()\n      } else {\n        while (true) {\n          const matched = fieldRegexp.exec(value)\n          if (matched === null) break\n          const result = vars[matched[0]]\n          if (result === undefined) {\n            throw new Error(`Variable ${matched[0]} not found`)\n          } else {\n            value = value.replaceAll(matched[0], result)\n            fieldRegexp.lastIndex = 0\n          }\n        }\n        return value\n      }\n    }\n    return value\n  }\n}\n","sourceCodeStart":368,"sourceCodeEnd":398,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/server/tool/src/initializer.ts#L368-L398","documentation":"fillValue substitutes variables of the form matched by fieldRegexp (e.g. {{name}}-style placeholders) from a vars lookup map. When a placeholder is found in the string but has no entry in vars, the value cannot be resolved, so it throws naming the missing variable. The loop repeats until no placeholders remain, so any unresolved variable aborts the fill.","triggerScenarios":"fillProps/fillValue encountering a placeholder in a property value whose key (matched[0], including delimiters) is absent from the vars map — e.g. variable defined with a different key spelling, or vars not populated for this step.","commonSituations":"Migration templates referencing a variable that was never registered; variables keyed without the regexp delimiters in the map while the lookup uses matched[0] (with delimiters); renamed variables in templates without updating the vars source (config/account data).","solutions":["Add the missing variable to the vars map with the exact key the regexp matches (including delimiters if matched[0] includes them)","Print the vars object and compare keys against the placeholders in the value","Fix the template typo in the property value"],"exampleFix":"// before\nconst value = 'Hello {{customerName}}' // vars has only { name: 'John' }\n// after\nconst vars = { ...baseVars, '{{customerName}}': customer.name } // key must match matched[0]\n// or fix the template to use an existing variable: 'Hello {{name}}'","handlingStrategy":"validation","validationCode":"function findUnresolvedVars(value: string, vars: Record<string, string>, regexp: RegExp): string[] {\n  const missing: string[] = []\n  for (const m of value.match(new RegExp(regexp.source, regexp.flags.replace('g', '') + 'g')) ?? []) {\n    if (vars[m] === undefined) missing.push(m)\n  }\n  return missing\n}\nconst missing = findUnresolvedVars(template, vars, fieldRegexp)\nif (missing.length > 0) throw new Error(`Unresolved variables: ${missing.join(', ')}`)","typeGuard":null,"tryCatchPattern":"try {\n  filled = await fillValue(value, vars)\n} catch (err) {\n  if (err instanceof Error && err.message.includes('not found')) {\n    const varName = err.message.match(/Variable (.+) not found/)?.[1]\n    console.error(`Add '${varName}' to vars or fix the template`, { available: Object.keys(vars) })\n  }\n  throw err\n}","preventionTips":["Keep variable keys consistent between the vars map and template placeholders (mind delimiter characters)","Pre-validate templates by extracting all placeholders and diffing against Object.keys(vars)","Centralize variable definitions so renames propagate to all templates"],"tags":["templating","variables","initializer"],"backgroundTag":"unresolved-template-variable","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}