hcengineering/platform · error · Error
Variable ${matched[0]} not found
Error message
Variable ${matched[0]} not found What it means
The Huly YAML header parser supports variable interpolation: any ${VAR} token found in a string header value is replaced with a value from the parser's `variables` map. If the token is not present in that map, resolveValue throws 'Variable ${VAR} not found'. This keeps undefined placeholders from silently leaking into imported data.
Source
Thrown at packages/importer/src/huly/parser.ts:69
;(data as any)[key] = this.resolveValue(value)
}
return data
}
private resolveValue (value: any): any {
if (typeof value === 'object') {
if (Array.isArray(value)) {
return value.map((v) => this.resolveValue(v))
} else {
return this.resolveProps(value)
}
} else if (typeof value === 'string') {
while (true) {
const matched = VARIABLE_REGEX.exec(value)
if (matched === null) break
const result = this.variables[matched[0]]
if (result === undefined) {
throw new Error(`Variable ${matched[0]} not found`)
} else {
value = value.replaceAll(matched[0], result)
VARIABLE_REGEX.lastIndex = 0
}
}
return value
}
return value
}
}
View on GitHub (pinned to 63e28dc964)
Solutions
- Add the missing key to the parser's variables map (or pass it where the HulyFormatImporter constructs the parser) so the token resolves.
- Correct or remove the ${...} placeholder in the file's YAML header if it is a typo or not needed.
- If the ${...} text is literal content, move it out of the YAML header into the markdown body, or escape/rewrite it so VARIABLE_REGEX does not match.
Example fix
// before (header uses undefined variable)
title: Guide for ${product}
// after (variable supplied to parser)
new HulyParser(variables: { '${product}': 'Huly' }) Defensive patterns
Strategy: try-catch
Validate before calling
// pre-scan header strings for unresolved variables
const used = [...JSON.stringify(header).matchAll(/\$\{[^}]+\}/g)].map((m) => m[0])
const missing = used.filter((v) => !(v in variables))
if (missing.length > 0) throw new Error(`Unresolved variables: ${missing.join(', ')}`) Try / catch
try {
const header = parser.readYamlHeader(filePath)
} catch (e) {
if ((e as Error).message.includes('not found') && /Variable \$\{/.test((e as Error).message)) {
const name = (e as Error).message.match(/Variable (\$\{[^}]+\})/)?.[1]
console.error(`Define '${name}' in parser variables or remove it from ${filePath}`)
} else throw e
} Prevention
- Keep the variables map co-located with the file set and cover all tokens used in headers.
- Avoid putting code samples containing ${...} in the YAML header; keep them in the markdown body.
- Lint headers for ${...} tokens and diff against the supplied variables before import.
- Watch for regex lastIndex state on the shared VARIABLE_REGEX when reusing the parser.
When it happens
Trigger: A YAML header in a parsed markdown file contains a ${...} placeholder (matching VARIABLE_REGEX) whose exact token (e.g. '${workspace}') is not a key in the variables passed to the parser; this runs during readYamlHeader -> resolveProps -> resolveValue, recursively for nested objects and arrays.
Common situations: Header references a variable the importer never defines; markdown content legitimately containing shell-style ${...} (e.g. code samples) placed in the YAML header; typo in variable name; variable defined with different casing or missing $ braces.
Related errors
- Tag should be inside master tag folder: ${currentPath}
- Unsupported card type: ${cardType} in ${cardPath}
- Invalid import schema in ${filePath}: ${errors.map((e) => `
- Template file not found: ${templatePath}
- Category not found: ${header.category}
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/ff8ed4470d9631dd.
Report an issue: GitHub.