{"record":{"id":"0c523465c4e225cd","repo":"can1357/oh-my-pi","slug":"invalid-config-file-path-configpath","errorCode":null,"errorMessage":"Invalid config file path: ${configPath}","messagePattern":"Invalid config file path: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/config/config-file.ts","lineNumber":163,"sourceCode":"\t\treadonly id: string,\n\t\tschema: Type | ConfigSchemaSource,\n\t\tconfigPath: string = path.join(getAgentDir(), `${id}.yml`),\n\t) {\n\t\tthis.#schemaSource = typeof schema === \"function\" ? { kind: \"eager\", schema } : schema;\n\t\tthis.#basePath = configPath;\n\t\tif (configPath.endsWith(\".yml\")) {\n\t\t\tthis.#yamlFallbackPath = `${configPath.slice(0, -4)}.yaml`;\n\t\t\tthis.#jsonMigrationPath = `${configPath.slice(0, -4)}.json`;\n\t\t} else if (configPath.endsWith(\".yaml\")) {\n\t\t\tthis.#yamlFallbackPath = null;\n\t\t\tthis.#jsonMigrationPath = `${configPath.slice(0, -5)}.json`;\n\t\t} else if (configPath.endsWith(\".json\") || configPath.endsWith(\".jsonc\")) {\n\t\t\tthis.#yamlFallbackPath = null;\n\t\t\t// JSON configs are still supported without migration.\n\t\t\tthis.#jsonMigrationPath = null;\n\t\t} else {\n\t\t\tthis.#yamlFallbackPath = null;\n\t\t\tthrow new Error(`Invalid config file path: ${configPath}`);\n\t\t}\n\t}\n\n\tget schema(): Type {\n\t\tif (this.#schemaSource.kind === \"eager\") return this.#schemaSource.schema;\n\t\tif (!this.#resolvedSchema) this.#resolvedSchema = this.#schemaSource.resolve();\n\t\treturn this.#resolvedSchema;\n\t}\n\n\t/**\n\t * Run the JSON → YAML migration synchronously, if applicable. Idempotent.\n\t * Sync callers (tests, settings init) hit this implicitly via {@link tryLoad}.\n\t */\n\t#ensureMigrated(): void {\n\t\tif (!this.#jsonMigrationPath) return;\n\t\tif (this.#yamlFallbackPath && !fs.existsSync(this.#basePath) && fs.existsSync(this.#yamlFallbackPath)) {\n\t\t\treturn;\n\t\t}","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/config/config-file.ts#L145-L181","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Rename the config file to use a supported extension: .yml (default), .yaml, .json, or .jsonc","If generating the path in code, force a valid suffix, e.g. ensure the override ends with '.yml' before passing it","Check env vars / CLI flags that supply the config path for typos or stale values pointing at old-format files"],"exampleFix":"// before\nconst cfg = new ConfigFile(\"myconfig\", schema, path.join(dir, \"config.toml\"));\n// after\nconst cfg = new ConfigFile(\"myconfig\", schema, path.join(dir, \"config.yml\"));","handlingStrategy":"validation","validationCode":"const VALID = /\\.(ya?ml|jsonc?)$/;\nfunction assertValidConfigPath(p: string): void {\n\tif (!VALID.test(p)) throw new Error(`Config path must end in .yml/.yaml/.json/.jsonc, got: ${p}`);\n}","typeGuard":"const isValidConfigPath = (p: string): boolean => /\\.(ya?ml|jsonc?)$/.test(p);","tryCatchPattern":"let cfg: ConfigFile<MyConfig>;\ntry {\n\tcfg = new ConfigFile(id, schema, configPath);\n} catch (err) {\n\tlogger.warn(\"Invalid config path, falling back to default\", { configPath, err });\n\tcfg = new ConfigFile(id, schema);\n}","preventionTips":["Always derive the config path with a fixed valid extension constant (e.g. `${id}.yml`)","Validate any user/env-supplied path override against /\\.(ya?ml|jsonc?)$/ before passing it in","Never concatenate raw external strings into the config path without checking the suffix"],"tags":["config","validation","programmer-error"],"backgroundTag":"unsupported-config-file-extension","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}