can1357/oh-my-pi · error

Invalid config file path: ${configPath}

Error message

Invalid config file path: ${configPath}

What it means

ConfigFile's constructor only accepts config paths ending in .yml, .yaml, .json, or .jsonc. Any other extension (or no extension) makes it impossible to pick a parser or a migration/fallback strategy, so it throws immediately at construction time. This is a programmer-error guard: fail fast before any file I/O happens.

Source

Thrown at packages/coding-agent/src/config/config-file.ts:163

		readonly id: string,
		schema: Type | ConfigSchemaSource,
		configPath: string = path.join(getAgentDir(), `${id}.yml`),
	) {
		this.#schemaSource = typeof schema === "function" ? { kind: "eager", schema } : schema;
		this.#basePath = configPath;
		if (configPath.endsWith(".yml")) {
			this.#yamlFallbackPath = `${configPath.slice(0, -4)}.yaml`;
			this.#jsonMigrationPath = `${configPath.slice(0, -4)}.json`;
		} else if (configPath.endsWith(".yaml")) {
			this.#yamlFallbackPath = null;
			this.#jsonMigrationPath = `${configPath.slice(0, -5)}.json`;
		} else if (configPath.endsWith(".json") || configPath.endsWith(".jsonc")) {
			this.#yamlFallbackPath = null;
			// JSON configs are still supported without migration.
			this.#jsonMigrationPath = null;
		} else {
			this.#yamlFallbackPath = null;
			throw new Error(`Invalid config file path: ${configPath}`);
		}
	}

	get schema(): Type {
		if (this.#schemaSource.kind === "eager") return this.#schemaSource.schema;
		if (!this.#resolvedSchema) this.#resolvedSchema = this.#schemaSource.resolve();
		return this.#resolvedSchema;
	}

	/**
	 * Run the JSON → YAML migration synchronously, if applicable. Idempotent.
	 * Sync callers (tests, settings init) hit this implicitly via {@link tryLoad}.
	 */
	#ensureMigrated(): void {
		if (!this.#jsonMigrationPath) return;
		if (this.#yamlFallbackPath && !fs.existsSync(this.#basePath) && fs.existsSync(this.#yamlFallbackPath)) {
			return;
		}

View on GitHub (pinned to 9690622007)

Solutions

  1. Rename the config file to use a supported extension: .yml (default), .yaml, .json, or .jsonc
  2. If generating the path in code, force a valid suffix, e.g. ensure the override ends with '.yml' before passing it
  3. Check env vars / CLI flags that supply the config path for typos or stale values pointing at old-format files

Example fix

// before
const cfg = new ConfigFile("myconfig", schema, path.join(dir, "config.toml"));
// after
const cfg = new ConfigFile("myconfig", schema, path.join(dir, "config.yml"));
Defensive patterns

Strategy: validation

Validate before calling

const VALID = /\.(ya?ml|jsonc?)$/;
function assertValidConfigPath(p: string): void {
	if (!VALID.test(p)) throw new Error(`Config path must end in .yml/.yaml/.json/.jsonc, got: ${p}`);
}

Type guard

const isValidConfigPath = (p: string): boolean => /\.(ya?ml|jsonc?)$/.test(p);

Try / catch

let cfg: ConfigFile<MyConfig>;
try {
	cfg = new ConfigFile(id, schema, configPath);
} catch (err) {
	logger.warn("Invalid config path, falling back to default", { configPath, err });
	cfg = new ConfigFile(id, schema);
}

Prevention

When it happens

Trigger: Calling `new ConfigFile(id, schema, path)` (or `relocate(path)`, which constructs a new ConfigFile) with a path whose extension is not .yml/.yaml/.json/.jsonc — e.g. config.txt, config.toml, config, or paths with trailing whitespace/queries.

Common situations: Pointing the agent at a config exported in another format (TOML, INI), constructing the path by concatenating a custom AGENT_DIR-style env var with a wrong suffix, or passing a directory path with no extension.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/0c523465c4e225cd. Report an issue: GitHub.