{"record":{"id":"4bdc3547867b6137","repo":"remoteintech/remote-jobs","slug":"missing-yaml-frontmatter-the-file-must-start-with","errorCode":null,"errorMessage":"Missing YAML frontmatter. The file must start with `---` followed by YAML fields and a closing `---`.","messagePattern":"Missing YAML frontmatter\\. The file must start with `---` followed by YAML fields and a closing `---`\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":".github/scripts/validate-companies.js","lineNumber":102,"sourceCode":" * Validate a single company file. Returns an array of error strings.\n */\nfunction validateCompanyFile(filePath) {\n  const errors = [];\n  const warnings = [];\n  let content;\n\n  try {\n    content = readFileSync(filePath, \"utf-8\");\n  } catch (err) {\n    errors.push(`Could not read file: ${err.message}`);\n    return { errors, warnings };\n  }\n\n  // Parse frontmatter\n  const data = parseFrontmatter(content);\n  if (!data) {\n    errors.push(\n      \"Missing YAML frontmatter. The file must start with `---` followed by YAML fields and a closing `---`.\"\n    );\n    return { errors, warnings };\n  }\n\n  // Check required fields\n  for (const field of REQUIRED_FIELDS) {\n    if (!data[field] || (typeof data[field] === \"string\" && !data[field].trim())) {\n      errors.push(`Missing required field: \\`${field}\\``);\n    }\n  }\n\n  // Validate enum values (only if field exists)\n  if (data.region && !VALID_REGIONS.includes(data.region)) {\n    errors.push(\n      `Invalid \\`region\\`: \"${data.region}\". Must be one of: ${VALID_REGIONS.join(\", \")}`\n    );\n  }\n","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/remoteintech/remote-jobs/blob/b1dd8deb1945e5ff58f9e9c35e318f53c8871930/.github/scripts/validate-companies.js#L84-L120","documentation":"After a successful read, parseFrontmatter (line 38) runs the regex /^---\\r?\\n([\\s\\S]*?)\\r?\\n---/. If it returns null the validator reports 'Missing YAML frontmatter' and returns at line 104. The regex requires a newline immediately after the opening `---` and immediately before the closing `---`, so a file beginning with `--- ` (trailing whitespace), `---title:...` (no newline), or a BOM/leading blank line will not match.","triggerScenarios":"File begins with prose instead of `---\\n`; opening fence has trailing whitespace (`--- `); opening fence lacks a following newline; a UTF-8 BOM sits before the first `---`; the frontmatter block was deleted during a merge; the file uses `~~~` instead of `---`.","commonSituations":"Contributor writes pure markdown without frontmatter; editor auto-trims trailing whitespace on save and corrupts the fence; BOM injected by a Windows editor; autoformatter inserts a leading blank line.","solutions":["Ensure the file starts literally with `---` followed by a newline, no leading characters.","Remove any UTF-8 BOM (`sed -i '1s/^\\xEF\\xBB\\xBF//' file.md`).","Close the frontmatter block with `---` on its own line.","Re-run the validator to confirm the error clears."],"exampleFix":"// before\n# Acme Corp\n\nAcme is a company...\n// after\n---\ntitle: \"Acme Corp\"\nslug: acme-corp\n---\n\n## Company blurb\n\nAcme is a company...","handlingStrategy":"validation","validationCode":"function hasFrontmatter(content) {\n  return /^---\\r?\\n[\\s\\S]*?\\r?\\n---/.test(content);\n}\n// before submitting:\nif (!hasFrontmatter(readFileSync(file, 'utf-8'))) {\n  fail('file must start with a ---\\n...\\n--- frontmatter block');\n}","typeGuard":"function hasFrontmatter(content) {\n  return typeof content === 'string' && /^---\\r?\\n[\\s\\S]*?\\r?\\n---/.test(content);\n}","tryCatchPattern":null,"preventionTips":["Start every new profile from a template that already has the fences.","Exclude the frontmatter fences from editor trim-whitespace-on-save.","Strip any UTF-8 BOM from contributed files."],"tags":["yaml","frontmatter","regex","parse"],"backgroundTag":null,"analyzedSha":"b1dd8deb1945e5ff58f9e9c35e318f53c8871930","analyzedAt":"2026-08-13T04:09:00.804Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}