{"record":{"id":"284a803ef112c0b5","repo":"can1357/oh-my-pi","slug":"failed-to-read-settings-config-filepath-stri","errorCode":null,"errorMessage":"Failed to read settings config ${filePath}: ${String(result.error)}","messagePattern":"Failed to read settings config (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/config/settings.ts","lineNumber":1496,"sourceCode":"\t\t\tpath: filePath,\n\t\t\tbackupPath,\n\t\t\terror: String(result.error),\n\t\t});\n\t\treturn { ...result, backupPath };\n\t}\n\n\t#unwrapYamlLoadResult(filePath: string, result: YamlLoadResult): RawSettings | null {\n\t\tswitch (result.kind) {\n\t\t\tcase \"missing\":\n\t\t\t\treturn null;\n\t\t\tcase \"loaded\":\n\t\t\t\treturn result.settings;\n\t\t\tcase \"invalid\":\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Settings config is invalid: ${filePath}${result.backupPath ? ` (moved to ${result.backupPath})` : \"\"}: ${String(result.error)}`,\n\t\t\t\t);\n\t\t\tcase \"unreadable\":\n\t\t\t\tthrow new Error(`Failed to read settings config ${filePath}: ${String(result.error)}`);\n\t\t}\n\t}\n\n\tasync #readExistingMainYaml(quarantineInvalid: boolean): Promise<MainYamlReadResult> {\n\t\tif (!this.#configPath) return { settings: null, configPath: null };\n\t\tfor (const filename of MAIN_CONFIG_FILENAMES) {\n\t\t\tconst configPath = path.join(this.#agentDir, filename);\n\t\t\tconst loaded = quarantineInvalid\n\t\t\t\t? await this.#loadYamlIfPresentForStartup(configPath)\n\t\t\t\t: this.#unwrapYamlLoadResult(configPath, await this.#loadYamlIfPresent(configPath, false));\n\t\t\tif (loaded) return { settings: loaded, configPath };\n\t\t}\n\t\treturn {\n\t\t\tsettings: null,\n\t\t\tconfigPath: path.join(this.#agentDir, MAIN_CONFIG_FILENAMES[0]),\n\t\t};\n\t}\n","sourceCodeStart":1478,"sourceCodeEnd":1514,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/config/settings.ts#L1478-L1514","documentation":"Thrown when reading the settings YAML fails at the I/O level (kind === \"unreadable\") — distinct from parse-invalid. The file exists in the expected location but could not be read, and the underlying OS error is stringified into the message.","triggerScenarios":"fs read of settings.yaml rejects with EACCES (no read permission), EISDIR (a directory named settings.yaml exists), EIO, or similar non-ENOENT errors.","commonSituations":"Permissions changed by another tool; a directory accidentally created where the file should be; failing disk or network mount holding the home directory.","solutions":["Check the embedded OS error: fix permissions (chmod/chown) for EACCES","Remove or rename the directory occupying the path if the error is EISDIR","Verify the filesystem/mount is healthy and retry"],"exampleFix":"// before\n$ ls -l ~/.omp/settings.yaml  # owned by root\n// after\n$ sudo chown $USER ~/.omp/settings.yaml","handlingStrategy":"try-catch","validationCode":"async function settingsReadable(path) {\n  try { await fs.promises.access(path, fs.constants.R_OK); return true; } catch { return false; }\n}","typeGuard":null,"tryCatchPattern":"try { const s = await loadSettings(); } catch (e) {\n  if (String(e).startsWith('Failed to read settings config')) {\n    logger.error('Settings file unreadable; check permissions/path', { error: String(e) });\n  } else throw e;\n}","preventionTips":["Keep config files readable by the running user (chmod u+r)","Ensure nothing replaced the file with a directory","Monitor mounts/disks that host the home directory"],"tags":["file-system","settings","permissions"],"backgroundTag":"file-read-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}