{"record":{"id":"4411b8628b4bd079","repo":"santifer/career-ops","slug":"config-profile-yml-not-found-fill-it-in-first","errorCode":null,"errorMessage":"config/profile.yml not found: fill it in first","messagePattern":"config/profile\\.yml not found: fill it in first","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/export-ats-text.mjs","lineNumber":234,"sourceCode":"  let profileRaw = null;\n  const profileSource = customProfilePath || process.env.CAREER_OPS_PROFILE || 'config/profile.yml';\n\n  if (customProfilePath) {\n    if (!existsSync(customProfilePath)) {\n      throw new Error(`Profile configuration file not found at: ${customProfilePath}`);\n    }\n    try {\n      const content = readFileSync(customProfilePath, 'utf8');\n      profileRaw = yaml.load(content);\n      if (!profileRaw || typeof profileRaw !== 'object') {\n        throw new Error(`Invalid YAML in profile file: ${customProfilePath}`);\n      }\n    } catch (err) {\n      throw new Error(`Failed to read profile file at ${customProfilePath}: ${err.message}`);\n    }\n  } else {\n    if (!existsSync(profileSource)) {\n      throw new Error('config/profile.yml not found: fill it in first');\n    }\n    try {\n      const content = readFileSync(profileSource, 'utf8');\n      profileRaw = yaml.load(content);\n      if (!profileRaw || typeof profileRaw !== 'object') {\n        throw new Error('config/profile.yml is empty or invalid YAML: fill it in first');\n      }\n    } catch (err) {\n      throw new Error(`Failed to read profile file at ${profileSource}: ${err.message}`);\n    }\n  }\n\n  let cvData = {};\n  const cvSource = customCvPath || process.env.CAREER_OPS_CV || 'cv.md';\n  if (customCvPath) {\n    if (!existsSync(customCvPath)) {\n      throw new Error(`CV file not found at: ${customCvPath}`);\n    }","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/santifer/career-ops/blob/1696bec4d021768e7359f9aad6b329cba883da20/scripts/export-ats-text.mjs#L216-L252","documentation":"When no customProfilePath argument is given, loadProfile falls back to CAREER_OPS_PROFILE or config/profile.yml and requires that default file to exist. This is the deliberate 'fails closed' onboarding gate: the exporter refuses to run on an uninitialized checkout instead of producing an empty ATS export. The message tells the user exactly which file to create.","triggerScenarios":"Calling loadProfile() (or loadProfile(null, cvPath)) in a repo where config/profile.yml does not exist and CAREER_OPS_PROFILE is unset — e.g. a fresh clone before onboarding, or running from a cwd where the relative path doesn't resolve.","commonSituations":"Fresh clone of career-ops before the first-run setup; running the script from a subdirectory so 'config/profile.yml' resolves wrong; CAREER_OPS_PROFILE set to a path that doesn't exist (env override also checked via existsSync and hits this same message); CI checkout without the gitignored personal config.","solutions":["Create and fill in config/profile.yml (name, email, phone, location, links) at the repository root — this is the intended fix per the onboarding steps.","If your profile lives elsewhere, either export CAREER_OPS_PROFILE=/abs/path/profile.yml or pass it as the first argument to loadProfile.","Run the exporter from the repository root (or fix the cwd) so the relative default path resolves."],"exampleFix":"// before\n$ node scripts/export-ats-text.mjs   # config/profile.yml missing\n\n// after\n$ export CAREER_OPS_PROFILE=$HOME/.career-ops/profile.yml\n$ node scripts/export-ats-text.mjs","handlingStrategy":"validation","validationCode":"import { existsSync } from 'node:fs';\nconst source = process.env.CAREER_OPS_PROFILE || 'config/profile.yml';\nif (!existsSync(source)) {\n  throw new Error(`Run first-run onboarding: create ${source} (see config/profile.example.yml)`);\n}\nloadProfile();","typeGuard":null,"tryCatchPattern":"try {\n  const profile = loadProfile();\n} catch (e) {\n  if (e.message.includes('config/profile.yml not found')) {\n    console.error('Setup incomplete: copy config/profile.example.yml to config/profile.yml and fill it in.');\n    process.exitCode = 1;\n  } else throw e;\n}","preventionTips":["Complete first-run onboarding (create config/profile.yml from the example) before running ATS exports.","Export CAREER_OPS_PROFILE in your shell profile or CI so the default path is explicit and absolute.","In CI, add a step asserting existsSync('config/profile.yml') before any script that loads the profile."],"tags":["configuration","onboarding","missing-file","env-var"],"backgroundTag":"missing-config-profile","analyzedSha":"1696bec4d021768e7359f9aad6b329cba883da20","analyzedAt":"2026-09-01T19:19:23.111Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}