can1357/oh-my-pi · error · Error
Failed to parse config overlay ${filePath}: ${String(error)}
Error message
Failed to parse config overlay ${filePath}: ${String(error)} What it means
The Settings loader parses config overlay files as YAML. When YAML.parse throws on the file's content, it wraps the failure with the file path and the underlying parser message so you know which overlay is malformed and why. This is a data-validation guard, not a runtime failure.
Source
Thrown at packages/coding-agent/src/config/settings.ts:1597
* missing or malformed files are hard errors so a typo'd path cannot
* silently fall back to the persistent settings.
*/
async #loadOverlayYaml(filePath: string, captureLegacyChangelogVersion = true): Promise<RawSettings> {
let content: string;
try {
content = await Bun.file(filePath).text();
} catch (error) {
throw new Error(
isEnoent(error)
? `Config overlay not found: ${filePath}`
: `Failed to read config overlay ${filePath}: ${String(error)}`,
);
}
let parsed: unknown;
try {
parsed = YAML.parse(content);
} catch (error) {
throw new Error(`Failed to parse config overlay ${filePath}: ${String(error)}`);
}
if (parsed === null || parsed === undefined) return {};
if (typeof parsed !== "object" || Array.isArray(parsed)) {
throw new Error(`Config overlay must be a YAML mapping: ${filePath}`);
}
return this.#migrateRawSettings(parsed as RawSettings, captureLegacyChangelogVersion);
}
async #migrateFromLegacy(): Promise<void> {
if (!this.#configPath) return;
let settings: RawSettings = {};
let migrated = false;
// 1. Migrate from settings.json
const settingsJsonPath = path.join(this.#agentDir, "settings.json");
try {
const parsed: unknown = JSONC.parse(await Bun.file(settingsJsonPath).text());View on GitHub (pinned to 9690622007)
Solutions
- Open the file named in the message and fix the YAML syntax at the reported line (the wrapped String(error) includes the parser's line/column).
- Validate the file first with a YAML linter or `bun -e 'require("yaml").parse(require("fs").readFileSync("<file>","utf8"))'`.
- Replace tabs with spaces and confirm consistent 2-space indentation.
- If the file is intentionally another format, rename it to the correct extension or convert it to YAML.
Example fix
// before (settings.overlay.yaml)
agent:
defaultModel: gpt-5
tools:
-write
// after
agent:
defaultModel: gpt-5
tools:
- write Defensive patterns
Strategy: validation
Validate before calling
import YAML from "yaml";
import { readFile } from "node:fs/promises";
try {
YAML.parse(await readFile(overlayPath, "utf8"));
} catch (e) {
console.error(`Fix YAML syntax in ${overlayPath}:`, e.message);
process.exit(1);
} Try / catch
try {
await settings.load();
} catch (e) {
if (String(e.message).startsWith("Failed to parse config overlay")) {
// surface path+parser detail to the user, fall back to defaults
} else throw e;
} Prevention
- Run a YAML linter in your editor / pre-commit hook for any settings file.
- Never use tabs for YAML indentation.
- Validate overlay files after template rendering and after sync tools merge them.
When it happens
Trigger: Loading a config overlay file whose bytes are not valid YAML — e.g. inconsistent indentation, unbalanced brackets/quotes, tabs for indentation, or a file in another format (JSON5/TOML) handed to a .yaml path.
Common situations: Hand-editing settings.yaml and leaving a dangling colon or wrong indent level; pasting JSON with tabs; a dotfile-sync tool merging conflicting versions; a template rendered with unfilled placeholders like ${VAR}.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Invalid config file path: ${readPath}
- Config overlay must be a YAML mapping: ${filePath}
- Invalid agent field: ${filePath}\n${content}
- Replacement text is not valid UTF-8: {err}
- Failed to load tree-sitter language: {err}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/671476d276eee487.
Report an issue: GitHub.