santifer/career-ops · warning

⚠️ config/profile.yml cv.sections lists

Error message

⚠️  config/profile.yml cv.sections lists "${shown}", but this CV's markup does not enclose that section on its own — leaving it in place, because moving it would leave tags unbalanced.

What it means

When reordering, generate-pdf.mjs extracts each named section as a self-contained HTML block. If a named section is present but its markup does not stand alone (it opens or closes elements outside its own span), moving it would leave unbalanced tags — so the section is left in place and this warning reports the no-op rather than silently ignoring the setting.

Solutions

  1. Fix the template so each section's markup is fully enclosed in its own block (open and close tags inside the section)
  2. If the template cannot change, remove that name from cv.sections and accept the template's default position
  3. Re-run PDF generation after fixing the markup and confirm the order applies

Example fix

<!-- before: unbalanced markup -->
<div class="sections">
  <h2>Skills</h2>
  <ul>...</ul>
<!-- experience opens inside skills wrapper -->
  <h2>Experience</h2>
</div>
<!-- after: each section self-contained -->
<section id="skills"><h2>Skills</h2><ul>...</ul></section>
<section id="experience"><h2>Experience</h2>...</section>
Defensive patterns

Strategy: validation

Validate before calling

// check that each named section's markup is self-contained before relying on reordering
for (const name of profile.cv?.sections ?? []) {
  if (!sectionBlockIsStandalone(html, name)) console.warn(`${name} markup is not self-contained; reorder will skip it`);
}

Type guard

const canReorder = (name, ambiguousSet) => !ambiguousSet.has(name);

Prevention

When it happens

Trigger: A cv.sections name resolves to a section that IS found in the CV but whose extracted HTML block is marked ambiguous (present in the `ambiguous` set) — the template wraps or splits its tags across sibling sections. Fired at generate-pdf.mjs:957 during reorderCvSections.

Common situations: A custom or hand-edited CV template (templates/cv-template.html) structures a section with elements spanning boundaries; a section heading sits outside its content wrapper so the block cannot be cleanly cut.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16). Data as JSON: /api/errors/0dfc30d02d2a8b5c. Report an issue: GitHub.

Appendix: source

Thrown at generate-pdf.mjs:958

    if (seen.has(name)) {
      console.warn(`⚠️  config/profile.yml cv.sections lists "${shown}" more than once — keeping its first position.`);
      continue;
    }
    seen.add(name);
    if (!CV_SECTION_KEYS.includes(name)) {
      console.warn(`⚠️  config/profile.yml cv.sections lists "${shown}", which is not a CV section — ignoring it. Recognized: ${CV_SECTION_KEYS.join(', ')}.`);
      continue;
    }
    const block = byKey.get(name);
    if (block) {
      chosen.push(block);
    } else if (ambiguous.has(name)) {
      // Present, but its markup doesn't stand on its own — it opens or closes
      // elements outside itself, so moving it would leave tags unbalanced.
      // Reported rather than skipped quietly: the section stays where the
      // template put it, and the user would otherwise see a setting that
      // silently does nothing.
      console.warn(`⚠️  config/profile.yml cv.sections lists "${shown}", but this CV's markup does not enclose that section on its own — leaving it in place, because moving it would leave tags unbalanced.`);
    } else {
      // Recognized and unambiguous but with no block. Ordinarily that just means
      // the section isn't in this CV (an optional one with no entries is
      // stripped before the PDF step), which is not worth a warning on its own.
      unresolved.push(name);
    }
  }

  // It is worth one when the CV also renders titles the alias table can't name,
  // because then "not in this CV" may be a misreading: the section could be
  // sitting right there under a heading nothing could identify.
  //
  // Whether that is what happened is not knowable here — an unresolved name may
  // equally be an optional section with no entries. So the report states only
  // what is checkable (this name matched nothing; these titles are unidentified)
  // and leaves the conclusion to the reader. Deliberately not conditioned on
  // whether the document changed: a name that did nothing did nothing, whether
  // or not its neighbours moved, and treating "output identical" as the failure

View on GitHub (pinned to aac998c7ed)