santifer/career-ops · warning

⚠️ config/profile.yml cv.sections lists only "${displayTitl

Error message

⚠️  config/profile.yml cv.sections lists only "${displayTitle(order[0])}". An order needs at least two sections — one name states no relationship, so nothing was changed.

What it means

reorderCvSections() in generate-pdf.mjs applies a configured section order from config/profile.yml cv.sections. An order with fewer than two names states no relationship between sections, so there is nothing to apply; the function warns (rather than staying silent) and returns the HTML unchanged so the user does not believe the setting took effect.

Source

Thrown at generate-pdf.mjs:753

 * too, in the order they should end up in.
 *
 * Runs before validateCvSectionOrder(), so the guard still judges what will
 * actually be printed — this satisfies the guard rather than bypassing it, which
 * is what separates it from --allow-reorder.
 *
 * No `cv.sections` → the input string is returned unchanged.
 *
 * @param {string} html
 * @param {string[]} order - Canonical section keys, e.g. ['skills', 'education'].
 * @returns {string}
 */
export function reorderCvSections(html, order) {
  if (!Array.isArray(order) || order.length === 0) return html;
  if (order.length < 2) {
    // Not an error, but not a no-op worth staying quiet about either: one name
    // states no relationship, so there is nothing to apply and the user would
    // otherwise be left thinking the setting took effect.
    console.warn(`⚠️  config/profile.yml cv.sections lists only "${displayTitle(order[0])}". An order needs at least two sections — one name states no relationship, so nothing was changed.`);
    return html;
  }

  // No early return on an empty block list: a CV whose sections are all
  // ambiguous produces none, and silently doing nothing is the failure mode
  // this feature exists to remove. The per-name loop below reports first.
  const { blocks, ambiguous, unrecognized } = extractSectionBlocks(html);

  const byKey = new Map();
  for (const block of blocks) {
    if (!byKey.has(block.key)) byKey.set(block.key, block);
  }

  const chosen = [];
  const unresolved = [];
  const seen = new Set();
  for (const name of order) {
    // `name` comes from a config file and is quoted straight into console

View on GitHub (pinned to 60398d6549)

Solutions

  1. Add a second (or more) section key to cv.sections so an actual ordering relationship exists
  2. If you only wanted to rename or drop one section, remove the cv.sections key entirely — the template order already applies

Example fix

# before (config/profile.yml)
cv:
  sections: [skills]

# after
cv:
  sections: [skills, experience, education]
Defensive patterns

Strategy: validation

Validate before calling

function cvSectionsApply(order) {
  // mirrors reorderCvSections: absent = fine, present needs >= 2 names
  return order == null || (Array.isArray(order) && order.length >= 2);
}

Type guard

/** @param {unknown} v */
function isUsableSections(v) {
  return v == null || (Array.isArray(v) && v.every(x => typeof x === 'string') && v.length >= 2);
}

Prevention

When it happens

Trigger: Setting `cv: sections: [skills]` (single-element array) or any one-entry list in config/profile.yml, then generating a PDF — order.length < 2 triggers the warning and the HTML passes through untouched.

Common situations: User starts building the cv.sections setting by listing the one section they care about, intending to add more later; a YAML nesting mistake collapses the list to one entry; copy-paste from an example leaves only the first item.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of santifer/career-ops@60398d6549 (2026-08-20). Data as JSON: /api/errors/c6d3b6553dcc4bab. Report an issue: GitHub.