santifer/career-ops · error · Error
is not valid YAML ( ) — refusing to overwrite it. Fix the…
Error message
${file} is not valid YAML (${String(err.message).split('
')[0]}) — refusing to overwrite it. Fix the file and re-run; nothing was changed. What it means
parsePluginConfig loads config/plugins.yml before writing enable/disable flags into it. If the file has content but yaml.load fails, it throws rather than proceeding — the library refuses to overwrite a file it cannot parse, since doing so would silently destroy the user's config. Nothing is modified when this fires.
Solutions
- Open config/plugins.yml and fix the YAML syntax — the error includes the parser's first error line to locate it
- Validate the file with a YAML linter or node -e "require('yaml').load(require('fs').readFileSync('config/plugins.yml','utf8'))"
- Replace tabs with spaces; ensure consistent 2-space indentation and quoted strings where needed
- Re-run the plugins command after the file parses cleanly
Example fix
// before (broken YAML: tab indentation)
plugins:
my-plugin:
enabled: true
// Error: config/plugins.yml is not valid YAML (bad indentation of a mapping entry) ...
// after
plugins:
my-plugin:
enabled: true Defensive patterns
Strategy: validation
Validate before calling
import { parseDocument } from 'yaml';
const doc = parseDocument(readFileSync('config/plugins.yml', 'utf8'));
if (doc.errors.length) throw new Error('plugins.yml has YAML errors: ' + doc.errors[0]); Type guard
null
Try / catch
try { await pluginsCmd.enable('my-plugin'); } catch (e) { if (e.message.includes('is not valid YAML')) { console.error(e.message); /* surface parser line, do not auto-rewrite */ } throw e; } Prevention
- Edit YAML with an editor that shows syntax errors; never use tabs
- Keep config/plugins.yml under version control so regressions are diffable
- Run a YAML linter in CI over config files
When it happens
Trigger: Calling the plugin enable/disable write path (e.g. plugins.mjs set/enable/disable) while config/plugins.yml contains malformed YAML — bad indentation, tabs, unclosed quotes, stray characters.
Common situations: Hand-editing plugins.yml with a tab character; merging config changes that broke indentation; copy-pasting YAML from docs with smart quotes; a truncated write from a crashed editor.
Related errors
- does not contain a YAML mapping — refusing to overwrite it…
- arbeitsagentur: entry
- Cannot read benchmarks at
- config/profile.yml is empty or invalid YAML: fill it in…
- ⚠️ Could not parse config/profile.yml
AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16).
Data as JSON: /api/errors/e161d2306deef653.
Report an issue: GitHub.
Appendix: source
Thrown at plugins.mjs:243
// Absent is not unreadable: no file means a first enable, which is the whole
// point of the function. Only an existing-but-unparseable file is a refusal.
if (raw == null) return {};
// An empty or comment-only file is "no config yet", not a corrupt one, and it
// must take the same path as an absent one. Decided from the text rather than
// from what the parser does with it: js-yaml 4 returns undefined for an empty
// document and js-yaml 5 throws "expected a document, but the input is empty",
// so inferring it from the parser would make this refuse to write over a
// comment-only config on one major and not the other.
const hasContent = raw.split('\n').some((line) => {
const t = line.trim();
return t !== '' && !t.startsWith('#');
});
if (!hasContent) return {};
let cfg;
try {
cfg = yaml.load(raw);
} catch (err) {
throw new Error(
`${file} is not valid YAML (${String(err.message).split('\n')[0]}) — refusing to overwrite it. `
+ 'Fix the file and re-run; nothing was changed.',
);
}
if (cfg == null) return {}; // empty file: same as absent
// A scalar or a list parses cleanly and is still not a config. Spreading one
// below would discard it just as silently as the empty object did.
if (typeof cfg !== 'object' || Array.isArray(cfg)) {
throw new Error(`${file} does not contain a YAML mapping — refusing to overwrite it. Nothing was changed.`);
}
return cfg;
}
// Write enabled:true/false into config/plugins.yml, merging (never clobbering
// the user's other plugins or non-secret settings).
function setEnabled(id, on, settings) {
const file = path.join(ROOT, 'config', 'plugins.yml');
const cfg = parsePluginConfig(existsSync(file) ? readFileSync(file, 'utf8') : null, file);View on GitHub (pinned to aac998c7ed)