chenglou/pretext · error · Error
Could not determine Unicode version from DerivedBidiClass he
Error message
Could not determine Unicode version from DerivedBidiClass header
What it means
Thrown by buildPayload() in the bidi-data generator when it cannot find a header comment line matching '# DerivedBidiClass-<version>.txt' inside the bundled Unicode source file. The script depends on that exact header to extract the Unicode version string that gets stamped into the generated src/generated/bidi-data.ts. Without it, generation cannot proceed because the version is load-bearing metadata for the output.
Source
Thrown at scripts/generate-bidi-data.ts:93
return { start, end }
}
function simplifyBidiType(raw: string): GeneratedBidiType {
if (generatedTypeToCode.has(raw as GeneratedBidiType)) return raw as GeneratedBidiType
if (bnProjectedTypes.has(raw)) return 'BN'
const longName = longBidiNames.get(raw)
if (longName !== undefined) return longName
throw new Error(`Unsupported bidi class ${raw}`)
}
function buildPayload(sourceText: string): GeneratedBidiPayload {
const sourceLines = sourceText.split(/\r?\n/)
const versionLine = sourceLines.find(line => line.startsWith('# DerivedBidiClass-'))
const versionMatch = versionLine?.match(/^# DerivedBidiClass-(.+)\.txt$/)
if (versionMatch === null || versionMatch === undefined) {
throw new Error('Could not determine Unicode version from DerivedBidiClass header')
}
const unicodeVersion = versionMatch[1]!
const bidiCodes = new Uint8Array(0x110000)
bidiCodes.fill(generatedTypeToCode.get('L')!)
for (let i = 0; i < sourceLines.length; i++) {
const rawLine = sourceLines[i]!
let rangeText: string | null = null
let typeText: string | null = null
if (rawLine.startsWith('# @missing:')) {
const missingMatch = rawLine.match(/^# @missing:\s*([0-9A-Fa-f]+(?:\.\.[0-9A-Fa-f]+)?)\s*;\s*([A-Za-z_]+)/)
if (missingMatch === null) continue
rangeText = missingMatch[1]!
typeText = missingMatch[2]!
} else {
const line = rawLine.split('#', 1)[0]!.trim()View on GitHub (pinned to ac49b09b7d)
Solutions
- Open scripts/unicode/DerivedBidiClass-17.0.0.txt and confirm the first comment line is exactly of the form `# DerivedBidiClass-17.0.0.txt`.
- If the file is missing or wrong, re-download the matching DerivedBidiClass.txt from the Unicode distribution for the version referenced by sourceFile in scripts/generate-bidi-data.ts:204 and place it at that path.
- If you intentionally changed the header format, update the regex at scripts/generate-bidi-data.ts:91 to match the new convention.
- If upgrading Unicode versions, also update the sourceFile path constant so it points at the new version's file.
Example fix
// before — header missing the trailing .txt # DerivedBidiClass-17.0.0 // after # DerivedBidiClass-17.0.0.txt
Defensive patterns
Strategy: validation
Validate before calling
import { readFileSync, existsSync } from 'node:fs'
function assertBidiSourceHeader(path: string): void {
if (!existsSync(path)) throw new Error(`Missing Unicode source: ${path}`)
const text = readFileSync(path, 'utf8')
const hasHeader = text.split(/\r?\n/).some(l => /^# DerivedBidiClass-.+\.txt$/.test(l))
if (!hasHeader) throw new Error(`DerivedBidiClass header not found in ${path}`)
}
assertBidiSourceHeader('scripts/unicode/DerivedBidiClass-17.0.0.txt') Try / catch
try {
await import('./generate-bidi-data.ts')
} catch (e) {
if (e instanceof Error && e.message.includes('DerivedBidiClass header')) {
console.error('Unicode source file is missing or its header changed. Re-fetch the matching DerivedBidiClass.txt and re-run.')
process.exit(1)
}
throw e
} Prevention
- Treat scripts/unicode/*.txt as committed, version-pinned inputs; never edit them by hand.
- When bumping the Unicode version, update both the sourceFile path constant and the committed .txt file in the same change.
When it happens
Trigger: Running `bun run generate:bidi-data` when scripts/unicode/DerivedBidiClass-17.0.0.txt is missing, truncated, has had its comment header stripped, or has been replaced with a Unicode release whose header line no longer ends in `.txt`. Also triggered if the file is empty or only contains data rows with no leading comment.
Common situations: A maintainer upgrades to a new Unicode version and drops in a fresh DerivedBidiClass file that uses a slightly different header convention; or the source file got corrupted by a line-ending normalizer that mangled the leading `#`; or someone deleted the unicode/ directory.
Related errors
- Generated bidi data is stale: ${outputPath}
- Built HTML not found for ${relativePath}
- Invalid code point range: ${raw}
- Unsupported bidi class ${raw}
AI-assisted analysis of chenglou/pretext@ac49b09b7d (2026-08-12).
Data as JSON: /api/errors/b7802de69ce74a52.
Report an issue: GitHub.