santifer/career-ops · warning
Cannot import generate-pdf.mjs
Error message
Cannot import generate-pdf.mjs (${e.code || e.message}) — skipping behavioral section-order tests What it means
generate-pdf.mjs imports Playwright at module scope, so dynamic import of it fails in environments without Playwright installed. test-all.mjs catches that import error and warns that the behavioral section-order tests are skipped rather than letting the suite crash.
Solutions
- Run `npm install` (or `npm i playwright && npx playwright install chromium`) in the repo root so the module imports.
- Read e.code/e.message in the warning: ERR_MODULE_NOT_FOUND → install deps; syntax errors → fix generate-pdf.mjs.
- If you only need the pure functions (sectionKey, validateCvSectionOrder), consider importing from a module that does not pull Playwright at top level.
- Accept the skip if CV rendering is irrelevant to your change — it is an intentional degradation.
Example fix
// before (generate-pdf.mjs)
import { chromium } from 'playwright';
// after (lazy, so importers without playwright still work)
let chromium;
export async function getChromium() { ({ chromium } = await import('playwright')); return chromium; } Defensive patterns
Strategy: try-catch
Validate before calling
let importable = true; try { await import(pathToFileURL('generate-pdf.mjs').href); } catch { importable = false; } if (!importable) console.warn('run npm install to enable pdf tests'); Type guard
const pdfImportable = (m) => m !== null && typeof m.validateCvSectionOrder === 'function';
Try / catch
try { pdfModule = await import(pathToFileURL(join(ROOT, 'generate-pdf.mjs')).href); } catch (e) { warn(`Cannot import generate-pdf.mjs (${e.code || e.message})`); } Prevention
- Always `npm install` after cloning and after package.json changes
- Keep Playwright imports out of modules that export pure logic
- Check e.code to distinguish missing deps from syntax errors
- Skip browser-dependent tests intentionally in slim CI jobs
When it happens
Trigger: `await import(pathToFileURL(join(ROOT, 'generate-pdf.mjs')).href)` rejects — typically with ERR_MODULE_NOT_FOUND because the playwright package is missing, or a syntax/compat error (non-zero e.code, message in e.message) in generate-pdf.mjs itself.
Common situations: Fresh clones without `npm install`, CI jobs that skip browser dependencies, Node version mismatch making the module fail to parse, or a broken generate-pdf.mjs after an edit.
Understand the failure class
Background: "X is not installed. Please install it with pip install Y": missing optional dependency errors — ImportError/ValueError raised when a library's optional extra was never installed — this error's family across 22 libraries.
Related errors
- archive render skipped — no Playwright browser in env
- Blocked request to restricted destination (DNS)
- Blocked request to restricted destination (DNS)
- Blocked request to restricted destination
- Blocked request to restricted destination
AI-assisted analysis of santifer/career-ops@e7abd431fc (2026-09-16).
Data as JSON: /api/errors/877d012a7cf93736.
Report an issue: GitHub.
Appendix: source
Thrown at test-all.mjs:2730
// Same gap, same two shipped Chinese markets (#3658): modes/zh-TW and modes/zh
// rendered titles the alias table could not name, so the guard was disabled AND
// cv.sections — the documented way to correct an order — silently did nothing.
// Both scripts are required: a CV written in either renders through this table.
for (const header of ['專業摘要', '工作經歷', '學歷', '證照', '技能', '专业摘要', '工作经历', '学历', '证书', '项目']) {
if (generatePdfScript.includes(`['${header}',`)) {
pass(`SECTION_ALIASES maps Chinese header: ${header}`);
} else {
fail(`SECTION_ALIASES missing Chinese header: ${header}`);
}
}
// generate-pdf.mjs imports playwright at module scope; degrade to a warning
// rather than crashing the suite where it is not installed.
let pdfModule = null;
try {
pdfModule = await import(pathToFileURL(join(ROOT, 'generate-pdf.mjs')).href);
} catch (e) {
warn(`Cannot import generate-pdf.mjs (${e.code || e.message}) — skipping behavioral section-order tests`);
}
if (pdfModule) {
const { sectionKey, validateCvSectionOrder } = pdfModule;
// Canonical keys are language-independent; only the spelling differs.
const keyCases = [
['Podsumowanie zawodowe', 'summary'],
['Kompetencje kluczowe', 'competencies'],
['Kluczowe kompetencje', 'competencies'], // word-order variant
['Doświadczenie zawodowe', 'experience'],
['Przebieg kariery', 'experience'],
['Wykształcenie', 'education'],
['Certyfikaty', 'certifications'],
['Umiejętności', 'skills'],
['Wyksztalcenie', 'education'], // diacritics stripped
['Umiejetnosci', 'skills'], // diacritics stripped
['Work Experience', 'experience'], // English must be unchangedView on GitHub (pinned to e7abd431fc)